[{"data":1,"prerenderedAt":601},["ShallowReactive",2],{"content-query-2YNb3zhcxH":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":595,"_id":596,"_source":597,"_file":598,"_stem":599,"_extension":600},"/technology-blogs/zh/2019","zh",false,"","论文精讲 | 一种隐私保护边云协同训练","为了解决前文中针对现有架构FedAvg提出的三个主要问题，我们提出了MistNet算法。MistNet算法将一个已完成预训练的DNN模型分割成两部分。","2022-12-16","https://obs-mindspore-file.obs.cn-north-4.myhuaweicloud.com/file/2022/12/20/6e863814a681436bb74a27ab63455687.png","technology-blogs","大V博文",{"type":15,"children":16,"toc":592},"root",[17,25,49,54,59,64,75,80,91,102,110,118,123,128,133,138,146,154,159,164,169,174,179,187,195,203,208,216,221,229,234,241,246,254,259,264,269,276,281,289,297,304,309,317,322,327,335,340,347,352,359,366,371,378,383,388,393,398,403,410,415,420,428,436,444,452,462,470,478,486,494,502,510,518,526,534,542,550,558,566,574,582,587],{"type":18,"tag":19,"props":20,"children":22},"element","h1",{"id":21},"论文精讲-一种隐私保护边云协同训练",[23],{"type":24,"value":8},"text",{"type":18,"tag":26,"props":27,"children":28},"p",{},[29,35,37,42,44],{"type":18,"tag":30,"props":31,"children":32},"strong",{},[33],{"type":24,"value":34},"作者",{"type":24,"value":36},"：",{"type":18,"tag":30,"props":38,"children":39},{},[40],{"type":24,"value":41},"王森、王鹏、姚信、崔金凯、胡钦涛、陈仁海、张弓",{"type":24,"value":43}," ｜**单位：**",{"type":18,"tag":30,"props":45,"children":46},{},[47],{"type":24,"value":48},"2012实验室理论部",{"type":18,"tag":26,"props":50,"children":51},{},[52],{"type":24,"value":53},"论文标题",{"type":18,"tag":26,"props":55,"children":56},{},[57],{"type":24,"value":58},"MistNet: Towards Private Neural Network Training with Local Differential Privacy",{"type":18,"tag":26,"props":60,"children":61},{},[62],{"type":24,"value":63},"论文链接",{"type":18,"tag":26,"props":65,"children":66},{},[67],{"type":18,"tag":68,"props":69,"children":73},"a",{"href":70,"rel":71},"https://github.com/TL-System/plato/blob/main/docs/papers/MistNet.pdf",[72],"nofollow",[74],{"type":24,"value":70},{"type":18,"tag":26,"props":76,"children":77},{},[78],{"type":24,"value":79},"代码链接",{"type":18,"tag":26,"props":81,"children":82},{},[83,85],{"type":24,"value":84},"Plato: ",{"type":18,"tag":68,"props":86,"children":89},{"href":87,"rel":88},"https://github.com/TL-System/plato",[72],[90],{"type":24,"value":87},{"type":18,"tag":26,"props":92,"children":93},{},[94,96],{"type":24,"value":95},"Sedna: ",{"type":18,"tag":68,"props":97,"children":100},{"href":98,"rel":99},"https://github.com/kubeedge/sedna",[72],[101],{"type":24,"value":98},{"type":18,"tag":26,"props":103,"children":104},{},[105],{"type":18,"tag":30,"props":106,"children":107},{},[108],{"type":24,"value":109},"01",{"type":18,"tag":26,"props":111,"children":112},{},[113],{"type":18,"tag":30,"props":114,"children":115},{},[116],{"type":24,"value":117},"研究背景",{"type":18,"tag":26,"props":119,"children":120},{},[121],{"type":24,"value":122},"在边缘AI领域，联邦学习概念最先由google提出并在学界和业界得到广泛的讨论和发展。对于边缘AI，数据异构和数据隐私是两个主要的挑战，而将联邦学习应用在边缘计算中，可以协助解决这些挑战。FedAvg通过主动选择每一轮参与训练的clients，避免了通信不可靠的问题，减少了通信过程中的压力。同时client只需要上传训练的gradients，防止了用户原生数据的泄露。但FedAvg仍然具备三个主要缺点:",{"type":18,"tag":26,"props":124,"children":125},{},[126],{"type":24,"value":127},"(1) 随着模型size的增加，传输量仍然会不断增长，成为系统性能的主要瓶颈之一。",{"type":18,"tag":26,"props":129,"children":130},{},[131],{"type":24,"value":132},"(2) 一些深度学习研究表明, gradients仍然部分包含原生数据的信息，攻击者可以通过它反推用户的隐私数据。",{"type":18,"tag":26,"props":134,"children":135},{},[136],{"type":24,"value":137},"(3) 边缘计算能力差异过大，一部分设备因算力不够，无法进行完整的训练过程或者会拖慢整个联邦学习的同步进度。",{"type":18,"tag":26,"props":139,"children":140},{},[141],{"type":18,"tag":30,"props":142,"children":143},{},[144],{"type":24,"value":145},"02",{"type":18,"tag":26,"props":147,"children":148},{},[149],{"type":18,"tag":30,"props":150,"children":151},{},[152],{"type":24,"value":153},"论文主要内容简介",{"type":18,"tag":26,"props":155,"children":156},{},[157],{"type":24,"value":158},"为了解决前文中针对现有架构FedAvg提出的三个主要问题，我们提出了MistNet算法。MistNet算法将一个已完成预训练的DNN模型分割成两部分。一部分作为特征提取器放在边缘侧；一部分作为预测器放在云上。根据深度学习的训练规律, 我们发现新加入的数据往往对特征提取器部分的参数更新很少，而主要将更新预测器的参数。因此，我们可以固定住边缘侧的参数部分，并将输入的数据通过特征提取器进行处理获得到对应的表征数据。然后我们将表征数据从client发送到server，并对预测器在云端进行训练。MistNet算法针对边缘场景进行了如下优化：",{"type":18,"tag":26,"props":160,"children":161},{},[162],{"type":24,"value":163},"(1) 减少边云网络传输通信量：将提取后的表征数据传输到云端进行表征数据聚合训练，而无须像传统联邦学习那样进行多轮的云边之间梯度的传输，减少了云边之间网络传输频次，从而减少了边云网络传输通信量。",{"type":18,"tag":26,"props":165,"children":166},{},[167],{"type":24,"value":168},"(2) 加强隐私保护效果：通过对表征数据的量化、加噪，完成表征数据的压缩和扰动，增大通过云端表征数据反推原始数据的难度，实现对数据的加强隐私保护效果。",{"type":18,"tag":26,"props":170,"children":171},{},[172],{"type":24,"value":173},"(3) 减少边侧计算资源需求：通过对预训练模型进行切割将模型的前几层作为表征提取器，减少在客户端的计算量。由于边侧的表征提取相当于是推理过程，因此通过这种方式可以实现仅具备推理能力的边侧硬件完成联邦学习。",{"type":18,"tag":26,"props":175,"children":176},{},[177],{"type":24,"value":178},"实验证明MistNet算法可以较FedAvg算法减少5倍通信开销，边缘计算量较FedAvg降低10倍。训练精度优于FedAvg，目标检测类学习任务自动化训练收敛效率较FedAvg提升30%。",{"type":18,"tag":26,"props":180,"children":181},{},[182],{"type":18,"tag":30,"props":183,"children":184},{},[185],{"type":24,"value":186},"03",{"type":18,"tag":26,"props":188,"children":189},{},[190],{"type":18,"tag":30,"props":191,"children":192},{},[193],{"type":24,"value":194},"算法框架与技术要点",{"type":18,"tag":26,"props":196,"children":197},{},[198],{"type":18,"tag":30,"props":199,"children":200},{},[201],{"type":24,"value":202},"技术要点1：模型切割和表征迁移方案",{"type":18,"tag":26,"props":204,"children":205},{},[206],{"type":24,"value":207},"利用深度神经网络前几层特征的可迁移性，服务器通过本领域或者相似领域现有数据训练模型，并提取前几层作为特征提取器。客户端从安全第三方或者服务器获得特征提取器，并可随机选择特征提取器和选择本地数据进行fine tune。",{"type":18,"tag":26,"props":209,"children":210},{},[211],{"type":18,"tag":212,"props":213,"children":215},"img",{"alt":7,"src":214},"https://obs-mindspore-file.obs.cn-north-4.myhuaweicloud.com/file/2023/02/03/95d1276a79d849099ac487f1dec37be5.png",[],{"type":18,"tag":26,"props":217,"children":218},{},[219],{"type":24,"value":220},"图一：表征提取技术示意图",{"type":18,"tag":26,"props":222,"children":223},{},[224],{"type":18,"tag":30,"props":225,"children":226},{},[227],{"type":24,"value":228},"技术要点2：表征数据的量化方案",{"type":18,"tag":26,"props":230,"children":231},{},[232],{"type":24,"value":233},"对中间层表征进行量化压缩处理可以有效的减少通信量。这里采用的是极致量化方案：对激活函数输出进行1 bit 量化。1 bit量化丢失了大部分的表征数据内容，有效地避免了信息泄露。",{"type":18,"tag":26,"props":235,"children":236},{},[237],{"type":18,"tag":212,"props":238,"children":240},{"alt":7,"src":239},"https://obs-mindspore-file.obs.cn-north-4.myhuaweicloud.com/file/2023/02/03/f4bd55db49fb4f8384f8b2416c02005c.png",[],{"type":18,"tag":26,"props":242,"children":243},{},[244],{"type":24,"value":245},"图二：通过量化技术减少表征数据的传输，并截断大部分数据信息",{"type":18,"tag":26,"props":247,"children":248},{},[249],{"type":18,"tag":30,"props":250,"children":251},{},[252],{"type":24,"value":253},"技术要点3：加噪量化表征隐私保护",{"type":18,"tag":26,"props":255,"children":256},{},[257],{"type":24,"value":258},"这里提出了两个解决方案：",{"type":18,"tag":26,"props":260,"children":261},{},[262],{"type":24,"value":263},"1. 对量化表征做符合LDP（本地差分隐私）的处理",{"type":18,"tag":26,"props":265,"children":266},{},[267],{"type":24,"value":268},"2. 随机响应：一种对0和1二值数据实现LDP的方法",{"type":18,"tag":26,"props":270,"children":271},{},[272],{"type":18,"tag":212,"props":273,"children":275},{"alt":7,"src":274},"https://obs-mindspore-file.obs.cn-north-4.myhuaweicloud.com/file/2023/02/03/e0ca360ab7cf40a1b39a47f2ed83ce15.png",[],{"type":18,"tag":26,"props":277,"children":278},{},[279],{"type":24,"value":280},"图三：通过加噪技术进一步混淆表征数据内容，使得数据难以恢复",{"type":18,"tag":26,"props":282,"children":283},{},[284],{"type":18,"tag":30,"props":285,"children":286},{},[287],{"type":24,"value":288},"04",{"type":18,"tag":26,"props":290,"children":291},{},[292],{"type":18,"tag":30,"props":293,"children":294},{},[295],{"type":24,"value":296},"实验部署与结果",{"type":18,"tag":26,"props":298,"children":299},{},[300],{"type":18,"tag":212,"props":301,"children":303},{"alt":7,"src":302},"https://obs-mindspore-file.obs.cn-north-4.myhuaweicloud.com/file/2023/02/03/6ab402fd11ce4c6f9401e9372909018d.png",[],{"type":18,"tag":26,"props":305,"children":306},{},[307],{"type":24,"value":308},"图四：通过Sedna平台一键部署隐私保护边云协同训练框架",{"type":18,"tag":26,"props":310,"children":311},{},[312],{"type":18,"tag":30,"props":313,"children":314},{},[315],{"type":24,"value":316},"01.软硬件环境",{"type":18,"tag":26,"props":318,"children":319},{},[320],{"type":24,"value":321},"硬件：Atlas 800 90000 + Atlas 500 3000",{"type":18,"tag":26,"props":323,"children":324},{},[325],{"type":24,"value":326},"软件：Ubuntu 18.04.5 LTS x86_64 + Euler OS V2R8 + CANN 5.0.2 + Kubeedge 1.8.2 + Sedna 0.4.0",{"type":18,"tag":26,"props":328,"children":329},{},[330],{"type":18,"tag":30,"props":331,"children":332},{},[333],{"type":24,"value":334},"02. 测试结果",{"type":18,"tag":26,"props":336,"children":337},{},[338],{"type":24,"value":339},"表1. FedAvg训练每batch耗时包括数据处理耗时且占比较大，针对Mistnet由于其数据预处理在边侧做完，中心侧训练则没有这部分操作以及耗时。",{"type":18,"tag":26,"props":341,"children":342},{},[343],{"type":18,"tag":212,"props":344,"children":346},{"alt":7,"src":345},"https://obs-mindspore-file.obs.cn-north-4.myhuaweicloud.com/file/2023/02/03/031a8692a0284f668e55dd01f92c412e.png",[],{"type":18,"tag":26,"props":348,"children":349},{},[350],{"type":24,"value":351},"表2. GPU+Pytorch+Yolov5在MistNet框架下，在不同数据集上的mAP实验结果，其中Yolov5s代表原始的模型，Yolov-NA代表关闭数据增强的模型，Yolov5s-F代表用特征图训练的模型，Yolov5s-Q(1bit)代表增加1bit量化的模型，Yolov5s-QN( ϵ=10)代表即使用量化又添加噪声的模型，ϵ表示增加噪声的强度，ϵ越小代表添加噪声的强度越大。",{"type":18,"tag":26,"props":353,"children":354},{},[355],{"type":18,"tag":212,"props":356,"children":358},{"alt":7,"src":357},"https://obs-mindspore-file.obs.cn-north-4.myhuaweicloud.com/file/2023/02/03/28f48055b4df4470929f47cffc0aade0.png",[],{"type":18,"tag":26,"props":360,"children":361},{},[362],{"type":18,"tag":212,"props":363,"children":365},{"alt":7,"src":364},"https://obs-mindspore-file.obs.cn-north-4.myhuaweicloud.com/file/2023/02/03/f0159dfb89004f709a0893b5ef43dee4.png",[],{"type":18,"tag":26,"props":367,"children":368},{},[369],{"type":24,"value":370},"图五：输入图像与表征提取后的图像对比, 提取特征后利用隐私保护技术进行加密后传输，难以还原并识别原始图像，满足强隐私保护需求。",{"type":18,"tag":26,"props":372,"children":373},{},[374],{"type":18,"tag":212,"props":375,"children":377},{"alt":7,"src":376},"https://obs-mindspore-file.obs.cn-north-4.myhuaweicloud.com/file/2023/02/03/b9323d85c1fa41ed9c506dd718f25776.png",[],{"type":18,"tag":26,"props":379,"children":380},{},[381],{"type":24,"value":382},"图六：我们分别对一个简单的神经网络(左图)和ResNet18(右图)在CIFAR10上进行了训练，展示了模型大小、隐私和准确率的关系。",{"type":18,"tag":26,"props":384,"children":385},{},[386],{"type":24,"value":387},"从实验结果我们可以看出:",{"type":18,"tag":26,"props":389,"children":390},{},[391],{"type":24,"value":392},"(1)LDP噪声越大，泄露敏感信息越少，对精度的影响越大。",{"type":18,"tag":26,"props":394,"children":395},{},[396],{"type":24,"value":397},"(2)对于0.11%和6.99%的特征提取器在Ɛ=1是取得了较好的隐私保护和精度的平衡。",{"type":18,"tag":26,"props":399,"children":400},{},[401],{"type":24,"value":402},"(3)复杂的模型对噪声具有更强的抵抗能力；对于1.3%和5.8%的特征提取器在Ɛ=1时取得了较好的隐私保护和精度的平衡。",{"type":18,"tag":26,"props":404,"children":405},{},[406],{"type":18,"tag":212,"props":407,"children":409},{"alt":7,"src":408},"https://obs-mindspore-file.obs.cn-north-4.myhuaweicloud.com/file/2023/02/03/eb4af1bd51b74633aefc6fe336870fc7.png",[],{"type":18,"tag":26,"props":411,"children":412},{},[413],{"type":24,"value":414},"图七：针对模型反转攻击的防御效果。",{"type":18,"tag":26,"props":416,"children":417},{},[418],{"type":24,"value":419},"我们使用白盒子Model Inversion攻击，并使用SSIM来验证效果。其中SSIM小于0.3的时候，我们认为原始图像是无法识别的。从上面的图表可以看出：通过1-bit量化和LDP的保护，对于多数特征提取器都可以有效的抵抗模型反转攻击。",{"type":18,"tag":26,"props":421,"children":422},{},[423],{"type":18,"tag":30,"props":424,"children":425},{},[426],{"type":24,"value":427},"05",{"type":18,"tag":26,"props":429,"children":430},{},[431],{"type":18,"tag":30,"props":432,"children":433},{},[434],{"type":24,"value":435},"NPU+MindSpore+Yolov5的代码实现",{"type":18,"tag":26,"props":437,"children":438},{},[439],{"type":18,"tag":30,"props":440,"children":441},{},[442],{"type":24,"value":443},"代码主要包括以下模块：数据加载、网络设计、数据隐私保护设计、损失函数设计与训练器。",{"type":18,"tag":26,"props":445,"children":446},{},[447],{"type":18,"tag":30,"props":448,"children":449},{},[450],{"type":24,"value":451},"01. 数据加载：",{"type":18,"tag":453,"props":454,"children":456},"pre",{"code":455},"def _has_only_empty_bbox(anno):\n    return all(any(o \u003C= 1 for o in obj[\"bbox\"][2:]) for obj in anno)\n\n\ndef _count_visible_keypoints(anno):\n    return sum(sum(1 for v in ann[\"keypoints\"][2::3] if v > 0) for ann in anno)\n\n\ndef has_valid_annotation(anno):\n    \"\"\"Check annotation file.\"\"\"\n    # if it's empty, there is no annotation\n    if not anno:\n        return False\n    # if all boxes have close to zero area, there is no annotation\n    if _has_only_empty_bbox(anno):\n        return False\n    # keypoints task have a slight different criteria for considering\n    # if an annotation is valid\n    if \"keypoints\" not in anno[0]:\n        return True\n    # for keypoint detection tasks, only consider valid images those\n    # containing at least min_keypoints_per_image\n    if _count_visible_keypoints(anno) >= min_keypoints_per_image:\n        return True\n    return False\n\n\nclass COCOYoloDataset:\n    \"\"\"YOLOV5 Dataset for COCO.\"\"\"\n    def __init__(self, root, ann_file, remove_images_without_annotations=True,\n                 filter_crowd_anno=True, is_training=True):\n        self.coco = COCO(ann_file)\n        self.root = root\n        self.img_ids = list(sorted(self.coco.imgs.keys()))\n        self.filter_crowd_anno = filter_crowd_anno\n        self.is_training = is_training\n        self.mosaic = True\n        # filter images without any annotations\n        if remove_images_without_annotations:\n            img_ids = []\n            for img_id in self.img_ids:\n                ann_ids = self.coco.getAnnIds(imgIds=img_id, iscrowd=None)\n                anno = self.coco.loadAnns(ann_ids)\n                if has_valid_annotation(anno):\n                    img_ids.append(img_id)\n            self.img_ids = img_ids\n\n        self.categories = {cat[\"id\"]: cat[\"name\"] for cat in self.coco.cats.values()}\n\n        self.cat_ids_to_continuous_ids = {\n            v: i for i, v in enumerate(self.coco.getCatIds())\n        }\n        self.continuous_ids_cat_ids = {\n            v: k for k, v in self.cat_ids_to_continuous_ids.items()\n        }\n        self.count = 0\n\n    def _mosaic_preprocess(self, index, input_size):\n        labels4 = []\n        s = 384\n        self.mosaic_border = [-s // 2, -s // 2]\n        yc, xc = [int(random.uniform(-x, 2 * s + x)) for x in self.mosaic_border]\n        indices = [index] + [random.randint(0, len(self.img_ids) - 1) for _ in range(3)]\n        for i, img_ids_index in enumerate(indices):\n            coco = self.coco\n            img_id = self.img_ids[img_ids_index]\n            img_path = coco.loadImgs(img_id)[0][\"file_name\"]\n            img = Image.open(os.path.join(self.root, img_path)).convert(\"RGB\")\n            img = np.array(img)\n            h, w = img.shape[:2]\n\n            if i == 0:  # top left\n                img4 = np.full((s * 2, s * 2, img.shape[2]), 128, dtype=np.uint8)  # base image with 4 tiles\n                x1a, y1a, x2a, y2a = max(xc - w, 0), max(yc - h, 0), xc, yc  # xmin, ymin, xmax, ymax (large image)\n                x1b, y1b, x2b, y2b = w - (x2a - x1a), h - (y2a - y1a), w, h  # xmin, ymin, xmax, ymax (small image)\n            elif i == 1:  # top right\n                x1a, y1a, x2a, y2a = xc, max(yc - h, 0), min(xc + w, s * 2), yc\n                x1b, y1b, x2b, y2b = 0, h - (y2a - y1a), min(w, x2a - x1a), h\n            elif i == 2:  # bottom left\n                x1a, y1a, x2a, y2a = max(xc - w, 0), yc, xc, min(s * 2, yc + h)\n                x1b, y1b, x2b, y2b = w - (x2a - x1a), 0, w, min(y2a - y1a, h)\n            elif i == 3:  # bottom right\n                x1a, y1a, x2a, y2a = xc, yc, min(xc + w, s * 2), min(s * 2, yc + h)\n                x1b, y1b, x2b, y2b = 0, 0, min(w, x2a - x1a), min(y2a - y1a, h)\n\n            img4[y1a:y2a, x1a:x2a] = img[y1b:y2b, x1b:x2b]  # img4[ymin:ymax, xmin:xmax]\n\n            padw = x1a - x1b\n            padh = y1a - y1b\n\n            ann_ids = coco.getAnnIds(imgIds=img_id)\n            target = coco.loadAnns(ann_ids)\n            # filter crowd annotations\n            if self.filter_crowd_anno:\n                annos = [anno for anno in target if anno[\"iscrowd\"] == 0]\n            else:\n                annos = [anno for anno in target]\n\n            target = {}\n            boxes = [anno[\"bbox\"] for anno in annos]\n            target[\"bboxes\"] = boxes\n\n            classes = [anno[\"category_id\"] for anno in annos]\n            classes = [self.cat_ids_to_continuous_ids[cl] for cl in classes]\n            target[\"labels\"] = classes\n\n            bboxes = target['bboxes']\n            labels = target['labels']\n            out_target = []\n\n            for bbox, label in zip(bboxes, labels):\n                tmp = []\n                # convert to [x_min y_min x_max y_max]\n                bbox = self._convetTopDown(bbox)\n                tmp.extend(bbox)\n                tmp.append(int(label))\n                # tmp [x_min y_min x_max y_max, label]\n                out_target.append(tmp)  # 这里out_target是label的实际宽高，对应于图片中的实际度量\n\n            labels = out_target.copy()\n            labels = np.array(labels)\n            out_target = np.array(out_target)\n\n            labels[:, 0] = out_target[:, 0] + padw\n            labels[:, 1] = out_target[:, 1] + padh\n            labels[:, 2] = out_target[:, 2] + padw\n            labels[:, 3] = out_target[:, 3] + padh\n            labels4.append(labels)\n\n        if labels4:\n            labels4 = np.concatenate(labels4, 0)\n            np.clip(labels4[:, :4], 0, 2 * s, out=labels4[:, :4])  # use with random_perspective\n        flag = np.array([1])\n        return img4, labels4, input_size, flag\n\n    def __getitem__(self, index):\n        \"\"\"\n        Args:\n            index (int): Index\n\n        Returns:\n            (img, target) (tuple): target is a dictionary contains \"bbox\", \"segmentation\" or \"keypoints\",\n                generated by the image's annotation. img is a PIL image.\n        \"\"\"\n        coco = self.coco\n        img_id = self.img_ids[index]\n        img_path = coco.loadImgs(img_id)[0][\"file_name\"]\n        if not self.is_training:\n            img = Image.open(os.path.join(self.root, img_path)).convert(\"RGB\")\n            return img, img_id\n\n        input_size = [640, 640]\n        if self.mosaic and random.random() \u003C 0.5:\n            return self._mosaic_preprocess(index, input_size)\n        img = np.fromfile(os.path.join(self.root, img_path), dtype='int8')\n        ann_ids = coco.getAnnIds(imgIds=img_id)\n        target = coco.loadAnns(ann_ids)\n        # filter crowd annotations\n        if self.filter_crowd_anno:\n            annos = [anno for anno in target if anno[\"iscrowd\"] == 0]\n        else:\n            annos = [anno for anno in target]\n\n        target = {}\n        boxes = [anno[\"bbox\"] for anno in annos]\n        target[\"bboxes\"] = boxes\n\n        classes = [anno[\"category_id\"] for anno in annos]\n        classes = [self.cat_ids_to_continuous_ids[cl] for cl in classes]\n        target[\"labels\"] = classes\n\n        bboxes = target['bboxes']\n        labels = target['labels']\n        out_target = []\n        for bbox, label in zip(bboxes, labels):\n            tmp = []\n            # convert to [x_min y_min x_max y_max]\n            bbox = self._convetTopDown(bbox)\n            tmp.extend(bbox)\n            tmp.append(int(label))\n            # tmp [x_min y_min x_max y_max, label]\n            out_target.append(tmp)\n        flag = np.array([0])\n        return img, out_target, input_size, flag\n\n    def __len__(self):\n        return len(self.img_ids)\n\n    def _convetTopDown(self, bbox):\n        x_min = bbox[0]\n        y_min = bbox[1]\n        w = bbox[2]\n        h = bbox[3]\n        return [x_min, y_min, x_min+w, y_min+h]\n\n\ndef create_yolo_dataset(image_dir, anno_path, batch_size, max_epoch, device_num, rank,\n                        config=None, is_training=True, shuffle=True):\n    \"\"\"Create dataset for YOLOV5.\"\"\"\n    cv2.setNumThreads(0)\n    de.config.set_enable_shared_mem(True)\n    if is_training:\n        filter_crowd = True\n        remove_empty_anno = True\n    else:\n        filter_crowd = False\n        remove_empty_anno = False\n\n    yolo_dataset = COCOYoloDataset(root=image_dir, ann_file=anno_path, filter_crowd_anno=filter_crowd,\n                                   remove_images_without_annotations=remove_empty_anno, is_training=is_training)\n    distributed_sampler = DistributedSampler(len(yolo_dataset), device_num, rank, shuffle=shuffle)\n    yolo_dataset.size = len(distributed_sampler)\n    hwc_to_chw = CV.HWC2CHW()\n\n    config.dataset_size = len(yolo_dataset)\n    cores = multiprocessing.cpu_count()\n    num_parallel_workers = int(cores / device_num)\n    if is_training:\n        multi_scale_trans = MultiScaleTrans(config, device_num)\n        yolo_dataset.transforms = multi_scale_trans\n\n        dataset_column_names = [\"image\", \"annotation\", \"input_size\", \"mosaic_flag\"]\n        output_column_names = [\"image\", \"annotation\", \"bbox1\", \"bbox2\", \"bbox3\",\n                               \"gt_box1\", \"gt_box2\", \"gt_box3\"]\n        map1_out_column_names = [\"image\", \"annotation\", \"size\"]\n        map2_in_column_names = [\"annotation\", \"size\"]\n        map2_out_column_names = [\"annotation\", \"bbox1\", \"bbox2\", \"bbox3\",\n                                 \"gt_box1\", \"gt_box2\", \"gt_box3\"]\n\n        ds = de.GeneratorDataset(yolo_dataset, column_names=dataset_column_names, sampler=distributed_sampler,\n                                 python_multiprocessing=True, num_parallel_workers=min(4, num_parallel_workers))\n        ds = ds.map(operations=multi_scale_trans, input_columns=dataset_column_names,\n                    output_columns=map1_out_column_names, column_order=map1_out_column_names,\n                    num_parallel_workers=min(12, num_parallel_workers), python_multiprocessing=True)\n        ds = ds.map(operations=PreprocessTrueBox(config), input_columns=map2_in_column_names,\n                    output_columns=map2_out_column_names, column_order=output_column_names,\n                    num_parallel_workers=min(4, num_parallel_workers), python_multiprocessing=False)\n        mean = [m * 255 for m in [0.485, 0.456, 0.406]]\n        std = [s * 255 for s in [0.229, 0.224, 0.225]]\n        ds = ds.map([CV.Normalize(mean, std),\n                     hwc_to_chw], num_parallel_workers=min(4, num_parallel_workers))\n\n        def concatenate(images):\n            images = np.concatenate((images[..., ::2, ::2], images[..., 1::2, ::2],\n                                     images[..., ::2, 1::2], images[..., 1::2, 1::2]), axis=0)\n            return images\n        ds = ds.map(operations=concatenate, input_columns=\"image\", num_parallel_workers=min(4, num_parallel_workers))\n        ds = ds.batch(batch_size, num_parallel_workers=min(4, num_parallel_workers), drop_remainder=True)\n    else:\n        ds = de.GeneratorDataset(yolo_dataset, column_names=[\"image\", \"img_id\"],\n                                 sampler=distributed_sampler)\n        compose_map_func = (lambda image, img_id: reshape_fn(image, img_id, config))\n        ds = ds.map(operations=compose_map_func, input_columns=[\"image\", \"img_id\"],\n                    output_columns=[\"image\", \"image_shape\", \"img_id\"],\n                    column_order=[\"image\", \"image_shape\", \"img_id\"],\n                    num_parallel_workers=8)\n        ds = ds.map(operations=hwc_to_chw, input_columns=[\"image\"], num_parallel_workers=8)\n        ds = ds.batch(batch_size, drop_remainder=True)\n    ds = ds.repeat(max_epoch)\n    return ds, len(yolo_dataset)\n",[457],{"type":18,"tag":458,"props":459,"children":460},"code",{"__ignoreMap":7},[461],{"type":24,"value":455},{"type":18,"tag":26,"props":463,"children":464},{},[465],{"type":18,"tag":30,"props":466,"children":467},{},[468],{"type":24,"value":469},"02. 网络****设计：",{"type":18,"tag":26,"props":471,"children":472},{},[473],{"type":18,"tag":30,"props":474,"children":475},{},[476],{"type":24,"value":477},"BackBone：切割为两部分，其中一部分在client端，另一部分在server端",{"type":18,"tag":453,"props":479,"children":481},{"code":480},"class YOLOv5Backbone_from(nn.Cell):\n\n    def __init__(self):\n        super(YOLOv5Backbone_from, self).__init__()\n        self.tenser_to_array = P.TupleToArray()\n        self.focusv2 = Focusv2(3, 32, k=3, s=1)\n        self.conv1 = Conv(32, 64, k=3, s=2)\n        self.C31 = C3(64, 64, n=1)\n        self.conv2 = Conv(64, 128, k=3, s=2)\n\n    def construct(self, x, input_shape):\n        \"\"\"construct method\"\"\"\n        #img_hight = P.Shape()(x)[2] * 2\n        #img_width = P.Shape()(x)[3] * 2\n        input_shape = F.shape(x)[2:4]\n        input_shape = F.cast(self.tenser_to_array(input_shape) * 2, ms.float32)\n\n        fcs = self.focusv2(x)\n        cv1 = self.conv1(fcs)\n        bcsp1 = self.C31(cv1)\n        cv2 = self.conv2(bcsp1)\n        return cv2, input_shape\n\nclass YOLOv5Backbone_to(nn.Cell):\n\n    def __init__(self):\n        super(YOLOv5Backbone_to, self).__init__()\n\n        self.C32 = C3(128, 128, n=3)\n        self.conv3 = Conv(128, 256, k=3, s=2)\n        self.C33 = C3(256, 256, n=3)\n        self.conv4 = Conv(256, 512, k=3, s=2)\n        self.spp = SPP(512, 512, k=[5, 9, 13])\n        self.C34 = C3(512, 512, n=1, shortcut=False)\n\n    def construct(self, cv2):\n        \"\"\"construct method\"\"\"\n        bcsp2 = self.C32(cv2)\n        cv3 = self.conv3(bcsp2)\n        bcsp3 = self.C33(cv3)\n        cv4 = self.conv4(bcsp3)\n        spp1 = self.spp(cv4)\n        bcsp4 = self.C34(spp1)\n        return bcsp2, bcsp3, bcsp4\n",[482],{"type":18,"tag":458,"props":483,"children":484},{"__ignoreMap":7},[485],{"type":24,"value":480},{"type":18,"tag":26,"props":487,"children":488},{},[489],{"type":18,"tag":30,"props":490,"children":491},{},[492],{"type":24,"value":493},"Server端整体网络架构：",{"type":18,"tag":453,"props":495,"children":497},{"code":496},"class YOLOV5s(nn.Cell):\n    \"\"\"\n    YOLOV5 network.\n\n    Args:\n        is_training: Bool. Whether train or not.\n\n    Returns:\n        Cell, cell instance of YOLOV5 neural network.\n\n    Examples:\n        YOLOV5s(True)\n    \"\"\"\n\n    def __init__(self, is_training):\n        super(YOLOV5s, self).__init__()\n        self.config = ConfigYOLOV5()\n\n        # YOLOv5 network\n        self.feature_map = YOLOv5(backbone=YOLOv5Backbone_to(),\n                                  out_channel=self.config.out_channel)\n\n        # prediction on the default anchor boxes\n        self.detect_1 = DetectionBlock('l', is_training=is_training)\n        self.detect_2 = DetectionBlock('m', is_training=is_training)\n        self.detect_3 = DetectionBlock('s', is_training=is_training)\n\n    def construct(self, x, img_hight, img_width, input_shape):\n\n        small_object_output, medium_object_output, big_object_output = self.feature_map(x, img_hight, img_width)\n        output_big = self.detect_1(big_object_output, input_shape)\n        output_me = self.detect_2(medium_object_output, input_shape)\n        output_small = self.detect_3(small_object_output, input_shape)\n        # big is the final output which has smallest feature map\n        return output_big, output_me, output_small\n",[498],{"type":18,"tag":458,"props":499,"children":500},{"__ignoreMap":7},[501],{"type":24,"value":496},{"type":18,"tag":453,"props":503,"children":505},{"code":504},"class YOLOv5(nn.Cell):\n    def __init__(self, backbone, out_channel):\n        super(YOLOv5, self).__init__()\n        self.out_channel = out_channel\n        self.backbone = backbone\n        #print(\"self.backbone: \", self.backbone)\n\n        self.conv1 = Conv(512, 256, k=1, s=1)  # 10\n        self.C31 = C3(512, 256, n=1, shortcut=False)  # 11\n        self.conv2 = Conv(256, 128, k=1, s=1)\n        self.C32 = C3(256, 128, n=1, shortcut=False)  # 13\n        self.conv3 = Conv(128, 128, k=3, s=2)\n        self.C33 = C3(256, 256, n=1, shortcut=False)  # 15\n        self.conv4 = Conv(256, 256, k=3, s=2)\n        self.C34 = C3(512, 512, n=1, shortcut=False)  # 17\n\n        self.backblock1 = YoloBlock(128, 255)\n        self.backblock2 = YoloBlock(256, 255)\n        self.backblock3 = YoloBlock(512, 255)\n\n        self.concat = P.Concat(axis=1)\n\n    def construct(self, x, img_hight, img_width):\n        \"\"\"\n        input_shape of x is (batch_size, 3, h, w)\n        feature_map1 is (batch_size, backbone_shape[2], h/8, w/8)\n        feature_map2 is (batch_size, backbone_shape[3], h/16, w/16)\n        feature_map3 is (batch_size, backbone_shape[4], h/32, w/32)\n        \"\"\"\n        #img_hight = P.Shape()(x)[2] * 2\n        #img_width = P.Shape()(x)[3] * 2\n\n        backbone4, backbone6, backbone9 = self.backbone(x)\n\n        cv1 = self.conv1(backbone9)  # 10\n        ups1 = P.ResizeNearestNeighbor((img_hight / 16, img_width / 16))(cv1)\n        concat1 = self.concat((ups1, backbone6))\n        bcsp1 = self.C31(concat1)  # 13\n        cv2 = self.conv2(bcsp1)\n        ups2 = P.ResizeNearestNeighbor((img_hight / 8, img_width / 8))(cv2)  # 15\n        concat2 = self.concat((ups2, backbone4))\n        bcsp2 = self.C32(concat2)  # 17\n        cv3 = self.conv3(bcsp2)\n\n        concat3 = self.concat((cv3, cv2))\n        bcsp3 = self.C33(concat3)  # 20\n        cv4 = self.conv4(bcsp3)\n        concat4 = self.concat((cv4, cv1))\n        bcsp4 = self.C34(concat4)  # 23\n        small_object_output = self.backblock1(bcsp2)  # h/8, w/8\n        medium_object_output = self.backblock2(bcsp3)  # h/16, w/16\n        big_object_output = self.backblock3(bcsp4)  # h/32, w/32\n        return small_object_output, medium_object_output, big_object_output\n",[506],{"type":18,"tag":458,"props":507,"children":508},{"__ignoreMap":7},[509],{"type":24,"value":504},{"type":18,"tag":26,"props":511,"children":512},{},[513],{"type":18,"tag":30,"props":514,"children":515},{},[516],{"type":24,"value":517},"03. 数据隐私保护设计：",{"type":18,"tag":453,"props":519,"children":521},{"code":520},"def encode_1b(x):\n    x[(x \u003C= 0)] = 0\n    x[(x > 0)] = 1\n    return x\n\ndef randomize_1b(bit_tensor, epsilon):\n    \"\"\"\n    The default unary encoding method is symmetric.\n    \"\"\"\n    #assert isinstance(bit_tensor, tensor), 'the type of input data is not matched with the expected type(tensor)'\n    return symmetric_tensor_encoding_1b(bit_tensor, epsilon)\n\ndef symmetric_tensor_encoding_1b(bit_tensor, epsilon):\n    p = mnp.exp(epsilon / 2) / (mnp.exp(epsilon / 2) + 1)\n    q = 1 / (mnp.exp(epsilon / 2) + 1)\n    return produce_random_response_1b(bit_tensor, p, q)\n\ndef produce_random_response_1b(bit_tensor, p, q=None):\n    \"\"\"\n    Implements random response as the perturbation method.\n    when using torch tensor, we use Uniform Distribution to create Binomial Distribution\n    because torch have not binomial function\n    \"\"\"\n    q = 1 - p if q is None else q\n    uniformreal = mindspore.ops.UniformReal(seed=2)\n    binomial = uniformreal(bit_tensor.shape)\n    zeroslike = mindspore.ops.ZerosLike()\n    oneslike = mindspore.ops.OnesLike()\n    p_binomial = mnp.where(binomial > q, oneslike(bit_tensor), zeroslike(bit_tensor))\n    q_binomial = mnp.where(binomial \u003C= q, oneslike(bit_tensor), zeroslike(bit_tensor))\n    return mnp.where(bit_tensor == 1, p_binomial, q_binomial) \n",[522],{"type":18,"tag":458,"props":523,"children":524},{"__ignoreMap":7},[525],{"type":24,"value":520},{"type":18,"tag":26,"props":527,"children":528},{},[529],{"type":18,"tag":30,"props":530,"children":531},{},[532],{"type":24,"value":533},"04. 损失函数设计：",{"type":18,"tag":453,"props":535,"children":537},{"code":536},"class YoloWithLossCell(nn.Cell):\n    \"\"\"YOLOV5 loss.\"\"\"\n    def __init__(self, network):\n        super(YoloWithLossCell, self).__init__()\n        self.yolo_network = network\n        self.config = ConfigYOLOV5()\n        self.loss_big = YoloLossBlock('l', self.config)\n        self.loss_me = YoloLossBlock('m', self.config)\n        self.loss_small = YoloLossBlock('s', self.config)\n\n    def construct(self, x, y_true_0, y_true_1, y_true_2, gt_0, gt_1, gt_2, img_hight, img_width, input_shape):\n        yolo_out = self.yolo_network(x, img_hight, img_width, input_shape)\n        loss_l = self.loss_big(*yolo_out[0], y_true_0, gt_0, input_shape)\n        loss_m = self.loss_me(*yolo_out[1], y_true_1, gt_1, input_shape)\n        loss_s = self.loss_small(*yolo_out[2], y_true_2, gt_2, input_shape)\n        return loss_l + loss_m + loss_s * 0.2\n\nclass TrainingWrapper(nn.Cell):\n    \"\"\"Training wrapper.\"\"\"\n    def __init__(self, network, optimizer, sens=1.0):\n        super(TrainingWrapper, self).__init__(auto_prefix=False)\n        self.network = network\n        self.network.set_grad()\n        self.weights = optimizer.parameters\n        self.optimizer = optimizer\n        self.grad = C.GradOperation(get_by_list=True, sens_param=True)\n        self.sens = sens\n        self.reducer_flag = False\n        self.grad_reducer = None\n        self.parallel_mode = context.get_auto_parallel_context(\"parallel_mode\")\n        if self.parallel_mode in [ParallelMode.DATA_PARALLEL, ParallelMode.HYBRID_PARALLEL]:\n            self.reducer_flag = True\n        if self.reducer_flag:\n            mean = context.get_auto_parallel_context(\"gradients_mean\")\n            if auto_parallel_context().get_device_num_is_set():\n                degree = context.get_auto_parallel_context(\"device_num\")\n            else:\n                degree = get_group_size()\n            self.grad_reducer = nn.DistributedGradReducer(optimizer.parameters, mean, degree)\n\n    def construct(self, *args):\n        weights = self.weights\n        loss = self.network(*args)\n        sens = P.Fill()(P.DType()(loss), P.Shape()(loss), self.sens)\n        grads = self.grad(self.network, weights)(*args, sens)\n        if self.reducer_flag:\n            grads = self.grad_reducer(grads)\n        return F.depend(loss, self.optimizer(grads))\n\n\n\n\nclass Giou(nn.Cell):\n    \"\"\"Calculating giou\"\"\"\n\n    def __init__(self):\n        super(Giou, self).__init__()\n        self.cast = P.Cast()\n        self.reshape = P.Reshape()\n        self.min = P.Minimum()\n        self.max = P.Maximum()\n        self.concat = P.Concat(axis=1)\n        self.mean = P.ReduceMean()\n        self.div = P.RealDiv()\n        self.eps = 0.000001\n\n    def construct(self, box_p, box_gt):\n        \"\"\"construct method\"\"\"\n        box_p_area = (box_p[..., 2:3] - box_p[..., 0:1]) * (box_p[..., 3:4] - box_p[..., 1:2])\n        box_gt_area = (box_gt[..., 2:3] - box_gt[..., 0:1]) * (box_gt[..., 3:4] - box_gt[..., 1:2])\n        x_1 = self.max(box_p[..., 0:1], box_gt[..., 0:1])\n        x_2 = self.min(box_p[..., 2:3], box_gt[..., 2:3])\n        y_1 = self.max(box_p[..., 1:2], box_gt[..., 1:2])\n        y_2 = self.min(box_p[..., 3:4], box_gt[..., 3:4])\n        intersection = (y_2 - y_1) * (x_2 - x_1)\n        xc_1 = self.min(box_p[..., 0:1], box_gt[..., 0:1])\n        xc_2 = self.max(box_p[..., 2:3], box_gt[..., 2:3])\n        yc_1 = self.min(box_p[..., 1:2], box_gt[..., 1:2])\n        yc_2 = self.max(box_p[..., 3:4], box_gt[..., 3:4])\n        c_area = (xc_2 - xc_1) * (yc_2 - yc_1)\n        union = box_p_area + box_gt_area - intersection\n        union = union + self.eps\n        c_area = c_area + self.eps\n        iou = self.div(self.cast(intersection, ms.float32), self.cast(union, ms.float32))\n        res_mid0 = c_area - union\n        res_mid1 = self.div(self.cast(res_mid0, ms.float32), self.cast(c_area, ms.float32))\n        giou = iou - res_mid1\n        giou = C.clip_by_value(giou, -1.0, 1.0)\n        return giou\n",[538],{"type":18,"tag":458,"props":539,"children":540},{"__ignoreMap":7},[541],{"type":24,"value":536},{"type":18,"tag":453,"props":543,"children":545},{"code":544},"class Iou(nn.Cell):\n    \"\"\"Calculate the iou of boxes\"\"\"\n\n    def __init__(self):\n        super(Iou, self).__init__()\n        self.min = P.Minimum()\n        self.max = P.Maximum()\n\n    def construct(self, box1, box2):\n        \"\"\"\n        box1: pred_box [batch, gx, gy, anchors, 1,      4] ->4: [x_center, y_center, w, h]\n        box2: gt_box   [batch, 1,  1,  1,       maxbox, 4]\n        convert to topLeft and rightDown\n        \"\"\"\n        box1_xy = box1[:, :, :, :, :, :2]\n        box1_wh = box1[:, :, :, :, :, 2:4]\n        box1_mins = box1_xy - box1_wh / F.scalar_to_array(2.0)  # topLeft\n        box1_maxs = box1_xy + box1_wh / F.scalar_to_array(2.0)  # rightDown\n\n        box2_xy = box2[:, :, :, :, :, :2]\n        box2_wh = box2[:, :, :, :, :, 2:4]\n        box2_mins = box2_xy - box2_wh / F.scalar_to_array(2.0)\n        box2_maxs = box2_xy + box2_wh / F.scalar_to_array(2.0)\n\n        intersect_mins = self.max(box1_mins, box2_mins)\n        intersect_maxs = self.min(box1_maxs, box2_maxs)\n        intersect_wh = self.max(intersect_maxs - intersect_mins, F.scalar_to_array(0.0))\n        # P.squeeze: for effiecient slice\n        intersect_area = P.Squeeze(-1)(intersect_wh[:, :, :, :, :, 0:1]) * \\\n                         P.Squeeze(-1)(intersect_wh[:, :, :, :, :, 1:2])\n        box1_area = P.Squeeze(-1)(box1_wh[:, :, :, :, :, 0:1]) * P.Squeeze(-1)(box1_wh[:, :, :, :, :, 1:2])\n        box2_area = P.Squeeze(-1)(box2_wh[:, :, :, :, :, 0:1]) * P.Squeeze(-1)(box2_wh[:, :, :, :, :, 1:2])\n        iou = intersect_area / (box1_area + box2_area - intersect_area)\n        # iou : [batch, gx, gy, anchors, maxboxes]\n        return iou\n\n\nclass YoloLossBlock(nn.Cell):\n    \"\"\"\n    Loss block cell of YOLOV5 network.\n    \"\"\"\n\n    def __init__(self, scale, config=ConfigYOLOV5()):\n        super(YoloLossBlock, self).__init__()\n        self.config = config\n        if scale == 's':\n            # anchor mask\n            idx = (0, 1, 2)\n        elif scale == 'm':\n            idx = (3, 4, 5)\n        elif scale == 'l':\n            idx = (6, 7, 8)\n        else:\n            raise KeyError(\"Invalid scale value for DetectionBlock\")\n        self.anchors = Tensor([self.config.anchor_scales[i] for i in idx], ms.float32)\n        self.ignore_threshold = Tensor(self.config.ignore_threshold, ms.float32)\n        self.concat = P.Concat(axis=-1)\n        self.iou = Iou()\n        self.reduce_max = P.ReduceMax(keep_dims=False)\n        self.confidence_loss = ConfidenceLoss()\n        self.class_loss = ClassLoss()\n\n        self.reduce_sum = P.ReduceSum()\n        self.giou = Giou()\n\n    def construct(self, prediction, pred_xy, pred_wh, y_true, gt_box, input_shape):\n        \"\"\"\n        prediction : origin output from yolo\n        pred_xy: (sigmoid(xy)+grid)/grid_size\n        pred_wh: (exp(wh)*anchors)/input_shape\n        y_true : after normalize\n        gt_box: [batch, maxboxes, xyhw] after normalize\n        \"\"\"\n        object_mask = y_true[:, :, :, :, 4:5]\n        class_probs = y_true[:, :, :, :, 5:]\n        true_boxes = y_true[:, :, :, :, :4]\n\n        grid_shape = P.Shape()(prediction)[1:3]\n        grid_shape = P.Cast()(F.tuple_to_array(grid_shape[::-1]), ms.float32)\n\n        pred_boxes = self.concat((pred_xy, pred_wh))\n        true_wh = y_true[:, :, :, :, 2:4]\n        true_wh = P.Select()(P.Equal()(true_wh, 0.0),\n                             P.Fill()(P.DType()(true_wh),\n                                      P.Shape()(true_wh), 1.0),\n                             true_wh)\n        true_wh = P.Log()(true_wh / self.anchors * input_shape)\n        # 2-w*h for large picture, use small scale, since small obj need more precise\n        box_loss_scale = 2 - y_true[:, :, :, :, 2:3] * y_true[:, :, :, :, 3:4]\n\n        gt_shape = P.Shape()(gt_box)\n        gt_box = P.Reshape()(gt_box, (gt_shape[0], 1, 1, 1, gt_shape[1], gt_shape[2]))\n\n        # add one more dimension for broadcast\n        iou = self.iou(P.ExpandDims()(pred_boxes, -2), gt_box)\n        # gt_box is x,y,h,w after normalize\n        # [batch, grid[0], grid[1], num_anchor, num_gt]\n        best_iou = self.reduce_max(iou, -1)\n        # [batch, grid[0], grid[1], num_anchor]\n\n        # ignore_mask IOU too small\n        ignore_mask = best_iou \u003C self.ignore_threshold\n        ignore_mask = P.Cast()(ignore_mask, ms.float32)\n        ignore_mask = P.ExpandDims()(ignore_mask, -1)\n        # ignore_mask backpro will cause a lot maximunGrad and minimumGrad time consume.\n        # so we turn off its gradient\n        ignore_mask = F.stop_gradient(ignore_mask)\n\n        confidence_loss = self.confidence_loss(object_mask, prediction[:, :, :, :, 4:5], ignore_mask)\n        class_loss = self.class_loss(object_mask, prediction[:, :, :, :, 5:], class_probs)\n\n        object_mask_me = P.Reshape()(object_mask, (-1, 1))  # [8, 72, 72, 3, 1]\n        box_loss_scale_me = P.Reshape()(box_loss_scale, (-1, 1))\n        pred_boxes_me = xywh2x1y1x2y2(pred_boxes)\n        pred_boxes_me = P.Reshape()(pred_boxes_me, (-1, 4))\n        true_boxes_me = xywh2x1y1x2y2(true_boxes)\n        true_boxes_me = P.Reshape()(true_boxes_me, (-1, 4))\n        ciou = self.giou(pred_boxes_me, true_boxes_me)\n        ciou_loss = object_mask_me * box_loss_scale_me * (1 - ciou)\n        ciou_loss_me = self.reduce_sum(ciou_loss, ())\n        loss = ciou_loss_me * 4 + confidence_loss + class_loss\n        batch_size = P.Shape()(prediction)[0]\n        return loss / batch_size\n",[546],{"type":18,"tag":458,"props":547,"children":548},{"__ignoreMap":7},[549],{"type":24,"value":544},{"type":18,"tag":26,"props":551,"children":552},{},[553],{"type":18,"tag":30,"props":554,"children":555},{},[556],{"type":24,"value":557},"05. 训练器设计：",{"type":18,"tag":453,"props":559,"children":561},{"code":560},"def linear_warmup_lr(current_step, warmup_steps, base_lr, init_lr):\n    \"\"\"Linear learning rate.\"\"\"\n    lr_inc = (float(base_lr) - float(init_lr)) / float(warmup_steps)\n    lr = float(init_lr) + lr_inc * current_step\n    return lr\n\n\ndef warmup_step_lr(lr, lr_epochs, steps_per_epoch, warmup_epochs, max_epoch, gamma=0.1):\n    \"\"\"Warmup step learning rate.\"\"\"\n    base_lr = lr\n    warmup_init_lr = 0\n    total_steps = int(max_epoch * steps_per_epoch)\n    warmup_steps = int(warmup_epochs * steps_per_epoch)\n    milestones = lr_epochs\n    milestones_steps = []\n    for milestone in milestones:\n        milestones_step = milestone * steps_per_epoch\n        milestones_steps.append(milestones_step)\n\n    lr_each_step = []\n    lr = base_lr\n    milestones_steps_counter = Counter(milestones_steps)\n    for i in range(total_steps):\n        if i \u003C warmup_steps:\n            lr = linear_warmup_lr(i + 1, warmup_steps, base_lr, warmup_init_lr)\n        else:\n            lr = lr * gamma**milestones_steps_counter[i]\n        lr_each_step.append(lr)\n\n    return np.array(lr_each_step).astype(np.float32)\n\n\ndef multi_step_lr(lr, milestones, steps_per_epoch, max_epoch, gamma=0.1):\n    return warmup_step_lr(lr, milestones, steps_per_epoch, 0, max_epoch, gamma=gamma)\n\n\ndef step_lr(lr, epoch_size, steps_per_epoch, max_epoch, gamma=0.1):\n    lr_epochs = []\n    for i in range(1, max_epoch):\n        if i % epoch_size == 0:\n            lr_epochs.append(i)\n    return multi_step_lr(lr, lr_epochs, steps_per_epoch, max_epoch, gamma=gamma)\n\n\ndef warmup_cosine_annealing_lr(lr, steps_per_epoch, warmup_epochs, max_epoch, T_max, eta_min=0):\n    \"\"\"Cosine annealing learning rate.\"\"\"\n    base_lr = lr\n    warmup_init_lr = 0\n    total_steps = int(max_epoch * steps_per_epoch)\n    warmup_steps = int(warmup_epochs * steps_per_epoch)\n\n    lr_each_step = []\n    for i in range(total_steps):\n        last_epoch = i // steps_per_epoch\n        if i \u003C warmup_steps:\n            lr = linear_warmup_lr(i + 1, warmup_steps, base_lr, warmup_init_lr)\n        else:\n            lr = eta_min + (base_lr - eta_min) * (1. + math.cos(math.pi*last_epoch / T_max)) / 2\n        lr_each_step.append(lr)\n\n    return np.array(lr_each_step).astype(np.float32)\n\n\ndef warmup_cosine_annealing_lr_V2(lr, steps_per_epoch, warmup_epochs, max_epoch, T_max, eta_min=0):\n    \"\"\"Cosine annealing learning rate V2.\"\"\"\n    base_lr = lr\n    warmup_init_lr = 0\n    total_steps = int(max_epoch * steps_per_epoch)\n    warmup_steps = int(warmup_epochs * steps_per_epoch)\n\n    last_lr = 0\n    last_epoch_V1 = 0\n\n    T_max_V2 = int(max_epoch*1/3)\n\n    lr_each_step = []\n    for i in range(total_steps):\n        last_epoch = i // steps_per_epoch\n        if i \u003C warmup_steps:\n            lr = linear_warmup_lr(i + 1, warmup_steps, base_lr, warmup_init_lr)\n        else:\n            if i \u003C total_steps*2/3:\n                lr = eta_min + (base_lr - eta_min) * (1. + math.cos(math.pi*last_epoch / T_max)) / 2\n                last_lr = lr\n                last_epoch_V1 = last_epoch\n            else:\n                base_lr = last_lr\n                last_epoch = last_epoch-last_epoch_V1\n                lr = eta_min + (base_lr - eta_min) * (1. + math.cos(math.pi * last_epoch / T_max_V2)) / 2\n\n        lr_each_step.append(lr)\n    return np.array(lr_each_step).astype(np.float32)\n\n\ndef warmup_cosine_annealing_lr_sample(lr, steps_per_epoch, warmup_epochs, max_epoch, T_max, eta_min=0):\n    \"\"\"Warmup cosine annealing learning rate.\"\"\"\n    start_sample_epoch = 60\n    step_sample = 2\n    tobe_sampled_epoch = 60\n    end_sampled_epoch = start_sample_epoch + step_sample*tobe_sampled_epoch\n    max_sampled_epoch = max_epoch+tobe_sampled_epoch\n    T_max = max_sampled_epoch\n\n    base_lr = lr\n    warmup_init_lr = 0\n    total_steps = int(max_epoch * steps_per_epoch)\n    total_sampled_steps = int(max_sampled_epoch * steps_per_epoch)\n    warmup_steps = int(warmup_epochs * steps_per_epoch)\n\n    lr_each_step = []\n\n    for i in range(total_sampled_steps):\n        last_epoch = i // steps_per_epoch\n        if last_epoch in range(start_sample_epoch, end_sampled_epoch, step_sample):\n            continue\n        if i \u003C warmup_steps:\n            lr = linear_warmup_lr(i + 1, warmup_steps, base_lr, warmup_init_lr)\n        else:\n            lr = eta_min + (base_lr - eta_min) * (1. + math.cos(math.pi*last_epoch / T_max)) / 2\n        lr_each_step.append(lr)\n\n    assert total_steps == len(lr_each_step)\n    return np.array(lr_each_step).astype(np.float32)\n\n\ndef get_lr(args):\n    \"\"\"generate learning rate.\"\"\"\n    if args.lr_scheduler == 'exponential':\n        lr = warmup_step_lr(args.lr,\n                            args.lr_epochs,\n                            args.steps_per_epoch,\n                            args.warmup_epochs,\n                            args.max_epoch,\n                            gamma=args.lr_gamma,\n                            )\n    elif args.lr_scheduler == 'cosine_annealing':\n        lr = warmup_cosine_annealing_lr(args.lr, args.steps_per_epoch, args.warmup_epochs, args.max_epoch, args.T_max, args.eta_min)\n    elif args.lr_scheduler == 'cosine_annealing_V2':\n        lr = warmup_cosine_annealing_lr_V2(args.lr, args.steps_per_epoch, args.warmup_epochs, args.max_epoch, args.T_max, args.eta_min)\n    elif args.lr_scheduler == 'cosine_annealing_sample':\n        lr = warmup_cosine_annealing_lr_sample(args.lr, args.steps_per_epoch, args.warmup_epochs, args.max_epoch, args.T_max, args.eta_min)\n    else:\n        raise NotImplementedError(args.lr_scheduler)\n    return lr\n",[562],{"type":18,"tag":458,"props":563,"children":564},{"__ignoreMap":7},[565],{"type":24,"value":560},{"type":18,"tag":26,"props":567,"children":568},{},[569],{"type":18,"tag":30,"props":570,"children":571},{},[572],{"type":24,"value":573},"06",{"type":18,"tag":26,"props":575,"children":576},{},[577],{"type":18,"tag":30,"props":578,"children":579},{},[580],{"type":24,"value":581},"总结与展望",{"type":18,"tag":26,"props":583,"children":584},{},[585],{"type":24,"value":586},"本文提出了一种新颖的隐私保护边云协同训练方法。与以往需要边缘设备与云设备频繁通信的方法不同，MistNet只需要在训练时将中间特征从边缘上传到云端一次，显著的减少了边云网络传输通信量。本方法通过对表征数据的量化、加噪，完成表征数据的压缩和扰动，增大通过云端表征数据反推原始数据的难度，实现对数据的加强隐私保护效果。",{"type":18,"tag":26,"props":588,"children":589},{},[590],{"type":24,"value":591},"此外，通过对预训练模型进行切割将模型的前几层作为表征提取器，减少在客户端的计算量。本文MistNet算法进一步缓解了FedAvg等联邦学习存在的缺陷。基于联邦学习的传输通信量小，隐私保护强和边侧计算量低的新算法是值得进一步的研究。",{"title":7,"searchDepth":593,"depth":593,"links":594},4,[],"markdown","content:technology-blogs:zh:2019.md","content","technology-blogs/zh/2019.md","technology-blogs/zh/2019","md",1776506117609]