• [其他] YoloX(2)
     #------------------------# # darknet #------------------------# class Darknet(nn.Cell):     """ Darknet for yolox-darknet53 """     # number of block from dark2 to dark5.     depth2block = {21: [1, 2, 2, 1], 53: [2, 8, 8, 4]}      def __init__(             self,             depth,             in_channels=3,             stem_out_channels=32,             out_features=("dark3", "dark4", "dark5"),     ):         """         Args:             depth (int): depth of darknet used in model, usually use [21, 53] for this param.             in_channels (int): number of input channels, for example, use 3 for RGB image.             stem_out_channels (int): number of output channels of darknet stem.                 It decides channels of darknet layer2 to layer5.             out_features (Tuple[str]): desired output layer name.         """         super(Darknet, self).__init__()         assert out_features, "please provide output features of Darknet"         self.out_features = out_features         self.stem = nn.SequentialCell(             BaseConv(in_channels=in_channels, out_channels=stem_out_channels, ksize=3, stride=1, act="lrelu"),             *self.make_group_layer(stem_out_channels, num_blocks=1, stride=2),         )         in_channels = stem_out_channels * 2          num_blocks = Darknet.depth2block[depth]         # create darknet with `stem_out_channels` and `num_blocks` layers.         # to make model structure more clear, we don't use `for` statement in python.         self.dark2 = nn.SequentialCell(             *self.make_group_layer(in_channels=in_channels, num_blocks=num_blocks[0], stride=2)         )         in_channels *= 2  # 128         self.dark3 = nn.SequentialCell(             *self.make_group_layer(in_channels=in_channels, num_blocks=num_blocks[1], stride=2)         )         in_channels *= 2  # 256         self.dark4 = nn.SequentialCell(             *self.make_group_layer(in_channels=in_channels, num_blocks=num_blocks[2], stride=2)         )         in_channels *= 2  # 512         self.dark5 = nn.SequentialCell(             *self.make_group_layer(in_channels=in_channels, num_blocks=num_blocks[3], stride=2),             *self.make_spp_block([in_channels, in_channels * 2], in_channels * 2),         )      def make_group_layer(self, in_channels: int, num_blocks: int, stride: int = 1):         "starts with conv layer then has `num_blocks` `ResLayer`"         return [             BaseConv(in_channels, in_channels * 2, ksize=3, stride=stride, act="lrelu"),             *[(ResLayer(in_channels * 2)) for _ in range(num_blocks)],         ]      def make_spp_block(self, filters_list, in_filters):         """ spatial pyramid pooling block"""         m = nn.SequentialCell(             *[                 BaseConv(in_filters, filters_list[0], 1, stride=1, act="lrelu"),                 BaseConv(filters_list[0], filters_list[1], 3, stride=1, act="lrelu"),                 SPPBottleneck(                     in_channels=filters_list[1],                     out_channels=filters_list[0],                     activation="lrelu",                 ),                 BaseConv(filters_list[0], filters_list[1], 3, stride=1, act="lrelu"),                 BaseConv(filters_list[1], filters_list[0], 1, stride=1, act="lrelu"),             ]         )         return m      def construct(self, x):         """ forward """         outputs = {}         x = self.stem(x)         outputs["stem"] = x         x = self.dark2(x)         outputs["dark2"] = x         x = self.dark3(x)         outputs["dark3"] = x         x = self.dark4(x)         outputs["dark4"] = x         x = self.dark5(x)         outputs["dark5"] = x         return outputs["dark3"], outputs["dark4"], outputs["dark5"]  class CSPDarknet(nn.Cell):     """ Darknet with CSP block for yolox-s m l x"""      def __init__(             self,             dep_mul,             wid_mul,             out_features=("dark3", "dark4", "dark5"),             depthwise=False,             act="silu"     ):         super(CSPDarknet, self).__init__()         assert out_features, "please provide output features of Darknet"         self.out_features = out_features         Conv = DWConv if depthwise else BaseConv         base_channels = int(wid_mul * 64)         base_depth = max(round(dep_mul * 3), 1)          # stem         self.stem = Focus(3, base_channels, ksize=3, act=act)          # dark2         self.dark2 = nn.SequentialCell(             Conv(base_channels, base_channels * 2, 3, 2, act=act),             CSPLayer(                 base_channels * 2,                 base_channels * 2,                 n=base_depth,                 depthwise=depthwise,                 act=act,             ),         )          # dark3         self.dark3 = nn.SequentialCell(             Conv(base_channels * 2, base_channels * 4, 3, 2, act=act),             CSPLayer(                 base_channels * 4,                 base_channels * 4,                 n=base_depth * 3,                 depthwise=depthwise,                 act=act,             ),         )          # dark4         self.dark4 = nn.SequentialCell(             Conv(base_channels * 4, base_channels * 8, 3, 2, act=act),             CSPLayer(                 base_channels * 8,                 base_channels * 8,                 n=base_depth * 3,                 depthwise=depthwise,                 act=act,             ),         )          # dark5         self.dark5 = nn.SequentialCell(             Conv(base_channels * 8, base_channels * 16, 3, 2, act=act),             SPPBottleneck(base_channels * 16, base_channels * 16, activation=act),             CSPLayer(                 base_channels * 16,                 base_channels * 16,                 n=base_depth,                 shortcut=False,                 depthwise=depthwise,                 act=act,             ),         )      def construct(self, x):         """ forward """         outputs = {}         x = self.stem(x)         outputs["stem"] = x         x = self.dark2(x)         outputs["dark2"] = x         x = self.dark3(x)         outputs["dark3"] = x         x = self.dark4(x)         outputs["dark4"] = x         x = self.dark5(x)         outputs["dark5"] = x         return outputs["dark3"], outputs["dark4"], outputs["dark5"]  3.6.3 backbon+neck 两种结构,如下图所示:  YOLOFPN,采用Darknet为backbone,使用yolov3 baseline的Neck结构,都采用FPN结构进行融合  YOLOPAFPN, 在FPN基础上引入PAN结构   #------------------------# # YOLOFPN #------------------------# class YOLOFPN(nn.Cell):     """     YOLOFPN module, Darknet53 is the default backbone of this model     """      def __init__(self, input_w, input_h, depth=53, in_features=None):         super(YOLOFPN, self).__init__()         if in_features is None:             in_features = ["dark3", "dark4", "dark5"]         self.backbone = Darknet(depth)         self.in_features = in_features          # out 1         self.out1_cbl = self._make_cbl(512, 256, 1)         self.out1 = self._make_embedding([256, 512], 512 + 256)          # out 2         self.out2_cbl = self._make_cbl(256, 128, 1)         self.out2 = self._make_embedding([128, 256], 256 + 128)         # upsample         self.upsample0 = P.ResizeNearestNeighbor((input_h // 16, input_w // 16))         self.upsample1 = P.ResizeNearestNeighbor((input_h // 8, input_w // 8))      def _make_cbl(self, _in, _out, ks):         """ make cbl layer """         return BaseConv(_in, _out, ks, stride=1, act="lrelu")      def _make_embedding(self, filters_list, in_filters):         """ make embedding """         m = nn.SequentialCell(             *[                 self._make_cbl(in_filters, filters_list[0], 1),                 self._make_cbl(filters_list[0], filters_list[1], 3),                 self._make_cbl(filters_list[1], filters_list[0], 1),                 self._make_cbl(filters_list[0], filters_list[1], 3),                 self._make_cbl(filters_list[1], filters_list[0], 1),             ]         )         return m      def construct(self, inputs):         """ forward """         out_features = self.backbone(inputs)         x2, x1, x0 = out_features          #  yolo branch 1         x1_in = self.out1_cbl(x0)         x1_in = self.upsample0(x1_in)         x1_in = P.Concat(axis=1)([x1_in, x1])         out_dark4 = self.out1(x1_in)          #  yolo branch 2         x2_in = self.out2_cbl(out_dark4)         x2_in = self.upsample1(x2_in)         x2_in = P.Concat(axis=1)([x2_in, x2])         out_dark3 = self.out2(x2_in)         outputs = (out_dark3, out_dark4, x0)         return outputs  #------------------------# # YOLOPAFPN #------------------------# class YOLOPAFPN(nn.Cell):     """     YOLOv3 model. Darknet 53 is the default backbone of this model     """      def __init__(             self,             input_w,             input_h,             depth=1.0,             width=1.0,             in_features=("dark3", "dark4", "dark5"),             in_channels=None,             depthwise=False,             act="silu"     ):         super(YOLOPAFPN, self).__init__()         if in_channels is None:             in_channels = [256, 512, 1024]         self.input_w = input_w         self.input_h = input_h         self.backbone = CSPDarknet(depth, width, depthwise=depthwise, act=act)         self.in_features = in_features         self.in_channels = in_channels         Conv = DWConv if depthwise else BaseConv          self.upsample0 = P.ResizeNearestNeighbor((input_h // 16, input_w // 16))         self.upsample1 = P.ResizeNearestNeighbor((input_h // 8, input_w // 8))         self.lateral_conv0 = BaseConv(int(in_channels[2] * width), int(in_channels[1] * width), 1, 1, act=act)         self.C3_p4 = CSPLayer(             int(2 * in_channels[1] * width),             int(in_channels[1] * width),             round(3 * depth),             False,             depthwise=depthwise,             act=act         )         self.reduce_conv1 = BaseConv(             int(in_channels[1] * width), int(in_channels[0] * width), 1, 1, act=act         )         self.C3_p3 = CSPLayer(             int(2 * in_channels[0] * width),             int(in_channels[0] * width),             round(3 * depth),             False,             depthwise=depthwise,             act=act,         )         # bottom-up conv         self.bu_conv2 = Conv(             int(in_channels[0] * width), int(in_channels[0] * width), 3, 2, act=act         )         self.C3_n3 = CSPLayer(             int(2 * in_channels[0] * width),             int(in_channels[1] * width),             round(3 * depth),             False,             depthwise=depthwise,             act=act,         )          # bottom-up conv         self.bu_conv1 = Conv(             int(in_channels[1] * width), int(in_channels[1] * width), 3, 2, act=act         )         self.C3_n4 = CSPLayer(             int(2 * in_channels[1] * width),             int(in_channels[2] * width),             round(3 * depth),             False,             depthwise=depthwise,             act=act,         )         self.concat = P.Concat(axis=1)      def construct(self, inputs):         """         Args:             inputs: input images.          Returns:             Tuple[Tensor]: FPN feature.         """          x2, x1, x0 = self.backbone(inputs)         fpn_out0 = self.lateral_conv0(x0)  # 1024->512  /32         f_out0 = self.upsample0(fpn_out0)  # 512    /16         f_out0 = self.concat((f_out0, x1))  # 512->1024    /16         f_out0 = self.C3_p4(f_out0)  # 1024->512  /16          fpn_out1 = self.reduce_conv1(f_out0)  # 512->256  /16         f_out1 = self.upsample1(fpn_out1)  # 256  /8         f_out1 = self.concat((f_out1, x2))  # 256->512  /8         pan_out2 = self.C3_p3(f_out1)  # 512->256  /16          p_out1 = self.bu_conv2(pan_out2)  # 256->256  /16         p_out1 = self.concat((p_out1, fpn_out1))  # 256->512  /16         pan_out1 = self.C3_n3(p_out1)  # 512->512/16          p_out0 = self.bu_conv1(pan_out1)  # 512->512/32         p_out0 = self.concat((p_out0, fpn_out0))  # 512->1024/32         pan_out0 = self.C3_n4(p_out0)  # 1024->1024/32          return pan_out2, pan_out1, pan_out0 3.7 bbox iou计算相关 #------------------------# # bbox iou #------------------------# @constexpr def raise_bbox_error():     raise IndexError("Index error, shape of input must be 4!")  def bboxes_iou(bboxes_a, bboxes_b, xyxy=True):     """     calculate iou     Args:         bboxes_a:         bboxes_b:         xyxy:      Returns:      """     if bboxes_a.shape[1] != 4 or bboxes_b.shape[1] != 4:         raise_bbox_error()      if xyxy:         tl = P.Maximum()(bboxes_a[:, None, :2], bboxes_b[:, :2])          br = P.Minimum()(bboxes_a[:, None, 2:], bboxes_b[:, 2:])          area_a = bboxes_a[:, 2:] - bboxes_a[:, :2]         area_a = (area_a[:, 0:1] * area_a[:, 1:2]).squeeze(-1)          area_b = bboxes_b[:, 2:] - bboxes_b[:, :2]         area_b = (area_b[:, 0:1] * area_b[:, 1:2]).squeeze(-1)      else:         tl = P.Maximum()(             (bboxes_a[:, None, :2] - bboxes_a[:, None, 2:] / 2),             (bboxes_b[:, :2] - bboxes_b[:, 2:] / 2),         )         br = P.Minimum()(             (bboxes_a[:, None, :2] + bboxes_a[:, None, 2:] / 2),             (bboxes_b[:, :2] + bboxes_b[:, 2:] / 2),         )         area_a = (bboxes_a[:, 2:3] * bboxes_a[:, 3:4]).squeeze(-1)         area_b = (bboxes_b[:, 2:3] * bboxes_b[:, 3:4]).squeeze(-1)     en = (tl < br).astype(tl.dtype)     en = (en[..., 0:1] * en[..., 1:2]).squeeze(-1)     area_i = tl - br     area_i = (area_i[:, :, 0:1] * area_i[:, :, 1:2]).squeeze(-1) * en     return area_i / (area_a[:, None] + area_b - area_i)  def batch_bboxes_iou(batch_bboxes_a, batch_bboxes_b, xyxy=True):     """         calculate iou for one batch     Args:         batch_bboxes_a:         batch_bboxes_b:         xyxy:      Returns:      """     if batch_bboxes_a.shape[-1] != 4 or batch_bboxes_b.shape[-1] != 4:         raise_bbox_error()     ious = []     for i in range(len(batch_bboxes_a)):         if xyxy:             iou = bboxes_iou(batch_bboxes_a[i], batch_bboxes_b[i], True)         else:             iou = bboxes_iou(batch_bboxes_a[i], batch_bboxes_b[i], False)         iou = P.ExpandDims()(iou, 0)         ious.append(iou)     ious = P.Concat(axis=0)(ious)     return ious  3.8 模型、Loss相关 DetectionBlock为完整的yolox结构,用于声明后续训练声明网络结构  yololoss  ema指数移动平均,对模型权重进行加权平均,使其更加鲁棒  3.8.1 网络损失函数 和网络的预测结果一样,YOLOX网络的损失函数也由三个部分组成,分别是Reg部分、Obj部分和Cls部分。Reg部分是特征点的回归参数判断,Obj部分是特征点是否包含物体判断,Cls部分是特征点包含的物体的种类。  在YoloX中,物体的真实框落在哪些特征点内就由该特征点来预测。  对于每一个真实框需要求取所有特征点与它的空间位置情况,作为正样本的特征点需要满足以下几个特点:  1)特征点落在物体的真实框内;  2)特征点距离物体中心尽量要在一定半径内。  满足这两点保证了属于正样本的特征点会落在物体真实框内部,特征点中心与物体真实框中心要相近。但是这两个条件仅用作正样本的初步筛选,在YoloX中,使用了SimOTA方法进行动态的正样本数量分配。  在YoloX中,会计算一个Cost代价矩阵,代表每个真实框和每个特征点之间的代价关系,Cost代价矩阵由三个部分组成:  1)每个真实框和当前特征点预测框的重合程度;  2)每个真实框和当前特征点预测框的种类预测准确度;  3)每个真实框的中心是否落在了特征点的一定半径内。  Cost代价矩阵的目的是自适应的找到当前特征点应该去拟合的真实框,重合度越高越需要拟合,分类越准越需要拟合,在一定半径内越需要拟合。  在SimOTA中,不同目标设定不同的正样本数量(dynamic k),以旷视科技官方回答中的蚂蚁和西瓜为例子,传统的正样本分配方案常常为同一场景下的西瓜和蚂蚁分配同样的正样本数,那要么蚂蚁有很多低质量的正样本,要么西瓜仅仅只有一两个正样本,这样的结果对于哪个分配方式都是不合适的。  动态的正样本设置的关键在于如何确定k,SimOTA具体的做法是首先计算每个目标Cost最低的10特征点,然后把这十个特征点对应的预测框与真实框的IOU加起来求得最终的k。  因此,SimOTA的过程总结如下:  1)计算每个真实框和当前特征点预测框的重合程度;  2)计算将重合度最高的十个预测框与真实框的IOU加起来求得每个真实框的k,也就代表每个真实框有k个特征点与之对应;  3)计算每个真实框和当前特征点预测框的种类预测准确度;  4)判断真实框的中心是否落在了特征点的一定半径内;  5)计算Cost代价矩阵;  6)将Cost最低的k个点作为该真实框的正样本。  由前文所述可知,YoloX的损失由三个部分组成:  1.Reg部分,由SimOTA可以知道每个真实框对应的特征点,获取到每个框对应的特征点后,取出该特征点的预测框,利用真实框和预测框计算IOU损失,作为Reg部分的Loss组成。  2.Obj部分,由SimOTA可知道每个真实框对应的特征点,所有真实框对应的特征点都是正样本,剩余的特征点均为负样本,根据正负样本和特征点的是否包含物体的预测结果计算交叉熵损失,作为Obj部分的Loss组成。  3.Cls部分,由SimOTA可知道每个真实框对应的特征点,获取到每个框对应的特征点后,取出该特征点的种类预测结果,根据真实框的种类和特征点的种类预测结果计算交叉熵损失,作为Cls部分的Loss组成。  其中Cls和Obj部分采用的都是二值交叉熵损失(BCELoss),Reg部分采用的是IoULoss。值得注意的是,Cls和Reg部分只计算正样本的损失,而Obj既计算正样本也计算负样本的损失。  其中:  Lcls代表分类损失,Lreg代表定位损失,Lobj代表obj损失,λ代表定位损失的平衡系数,源码中设置是5.0,Npos代表被分为正样的Anchor Point数。  #------------------------# # yolox model #------------------------# class DetectionPerFPN(nn.Cell):     """ head  """      def __init__(self, num_classes, scale, in_channels=None, act="silu", width=1.0):         super(DetectionPerFPN, self).__init__()         if in_channels is None:             in_channels = [1024, 512, 256]         self.scale = scale         self.num_classes = num_classes         Conv = BaseConv         if scale == 's':             self.stem = BaseConv(in_channels=int(in_channels[0] * width), out_channels=int(256 * width), ksize=1,                                  stride=1, act=act)         elif scale == 'm':             self.stem = BaseConv(in_channels=int(in_channels[1] * width), out_channels=int(256 * width), ksize=1,                                  stride=1, act=act)         elif scale == 'l':             self.stem = BaseConv(in_channels=int(in_channels[2] * width), out_channels=int(256 * width), ksize=1,                                  stride=1, act=act)         else:             raise KeyError("Invalid scale value for DetectionBlock")          self.cls_convs = nn.SequentialCell(             [                 Conv(                     in_channels=int(256 * width),                     out_channels=int(256 * width),                     ksize=3,                     stride=1,                     act=act,                 ),                 Conv(                     in_channels=int(256 * width),                     out_channels=int(256 * width),                     ksize=3,                     stride=1,                     act=act,                 ),             ]         )         self.reg_convs = nn.SequentialCell(             [                 Conv(                     in_channels=int(256 * width),                     out_channels=int(256 * width),                     ksize=3,                     stride=1,                     act=act,                 ),                 Conv(                     in_channels=int(256 * width),                     out_channels=int(256 * width),                     ksize=3,                     stride=1,                     act=act,                 ),             ]         )         self.cls_preds = nn.Conv2d(in_channels=int(256 * width), out_channels=self.num_classes, kernel_size=1, stride=1,                                    pad_mode="pad", has_bias=True)          self.reg_preds = nn.Conv2d(in_channels=int(256 * width), out_channels=4, kernel_size=1, stride=1,                                    pad_mode="pad",                                    has_bias=True)          self.obj_preds = nn.Conv2d(in_channels=int(256 * width), out_channels=1, kernel_size=1, stride=1,                                    pad_mode="pad",                                    has_bias=True)      def construct(self, x):         """ forward """         x = self.stem(x)         cls_x = x         reg_x = x         cls_feat = self.cls_convs(cls_x)          cls_output = self.cls_preds(cls_feat)          reg_feat = self.reg_convs(reg_x)         reg_output = self.reg_preds(reg_feat)         obj_output = self.obj_preds(reg_feat)          return cls_output, reg_output, obj_output  class DetectionBlock(nn.Cell):     """ connect yolox backbone and head """      def __init__(self, config, backbone="yolopafpn"):         super(DetectionBlock, self).__init__()         self.num_classes = config.num_classes         self.attr_num = self.num_classes + 5         self.depthwise = config.depth_wise         self.strides = Tensor([8, 16, 32], mindspore.float32)         self.input_size = config.input_size          # network         if backbone == "yolopafpn":             self.backbone = YOLOPAFPN(depth=1.33, width=1.25, input_w=self.input_size[1], input_h=self.input_size[0])             self.head_inchannels = [1024, 512, 256]             self.activation = "silu"             self.width = 1.25         else:             self.backbone = YOLOFPN(input_w=self.input_size[1], input_h=self.input_size[0])             self.head_inchannels = [512, 256, 128]             self.activation = "lrelu"             self.width = 1.0          self.head_l = DetectionPerFPN(in_channels=self.head_inchannels, num_classes=self.num_classes, scale='l',                                       act=self.activation, width=self.width)         self.head_m = DetectionPerFPN(in_channels=self.head_inchannels, num_classes=self.num_classes, scale='m',                                       act=self.activation, width=self.width)         self.head_s = DetectionPerFPN(in_channels=self.head_inchannels, num_classes=self.num_classes, scale='s',                                       act=self.activation, width=self.width)      def construct(self, x):         """ forward """         outputs = []         x_l, x_m, x_s = self.backbone(x)         cls_output_l, reg_output_l, obj_output_l = self.head_l(x_l)  # (bs, 80, 80, 80)(bs, 4, 80, 80)(bs, 1, 80, 80)         cls_output_m, reg_output_m, obj_output_m = self.head_m(x_m)  # (bs, 80, 40, 40)(bs, 4, 40, 40)(bs, 1, 40, 40)         cls_output_s, reg_output_s, obj_output_s = self.head_s(x_s)  # (bs, 80, 20, 20)(bs, 4, 20, 20)(bs, 1, 20, 20)         if self.training:             output_l = P.Concat(axis=1)((reg_output_l, obj_output_l, cls_output_l))  # (bs, 85, 80, 80)             output_m = P.Concat(axis=1)((reg_output_m, obj_output_m, cls_output_m))  # (bs, 85, 40, 40)             output_s = P.Concat(axis=1)((reg_output_s, obj_output_s, cls_output_s))  # (bs, 85, 20, 20)              output_l = self.mapping_to_img(output_l, stride=self.strides[0])  # (bs, 6400, 85)x_c, y_c, w, h             output_m = self.mapping_to_img(output_m, stride=self.strides[1])  # (bs, 1600, 85)x_c, y_c, w, h             output_s = self.mapping_to_img(output_s, stride=self.strides[2])  # (bs,  400, 85)x_c, y_c, w, h          else:              output_l = P.Concat(axis=1)(                 (reg_output_l, P.Sigmoid()(obj_output_l), P.Sigmoid()(cls_output_l)))  # bs, 85, 80, 80              output_m = P.Concat(axis=1)(                 (reg_output_m, P.Sigmoid()(obj_output_m), P.Sigmoid()(cls_output_m)))  # bs, 85, 40, 40              output_s = P.Concat(axis=1)(                 (reg_output_s, P.Sigmoid()(obj_output_s), P.Sigmoid()(cls_output_s)))  # bs, 85, 20, 20             output_l = self.mapping_to_img(output_l, stride=self.strides[0])  # (bs, 6400, 85)x_c, y_c, w, h             output_m = self.mapping_to_img(output_m, stride=self.strides[1])  # (bs, 1600, 85)x_c, y_c, w, h             output_s = self.mapping_to_img(output_s, stride=self.strides[2])  # (bs,  400, 85)x_c, y_c, w, h         outputs.append(output_l)         outputs.append(output_m)         outputs.append(output_s)         return P.Concat(axis=1)(outputs)  # batch_size, 8400, 85      def mapping_to_img(self, output, stride):         """ map to origin image scale for each fpn """         batch_size = P.Shape()(output)[0]         n_ch = self.attr_num         grid_size = P.Shape()(output)[2:4]         range_x = range(grid_size[1])         range_y = range(grid_size[0])         stride = P.Cast()(stride, output.dtype)         grid_x = P.Cast()(F.tuple_to_array(range_x), output.dtype)         grid_y = P.Cast()(F.tuple_to_array(range_y), output.dtype)         grid_y = P.ExpandDims()(grid_y, 1)         grid_x = P.ExpandDims()(grid_x, 0)         yv = P.Tile()(grid_y, (1, grid_size[1]))         xv = P.Tile()(grid_x, (grid_size[0], 1))         grid = P.Stack(axis=2)([xv, yv])  # (80, 80, 2)         grid = P.Reshape()(grid, (1, 1, grid_size[0], grid_size[1], 2))  # (1,1,80,80,2)         output = P.Reshape()(output,                              (batch_size, n_ch, grid_size[0], grid_size[1]))  # bs, 6400, 85-->(bs,85,80,80)         output = P.Transpose()(output, (0, 2, 1, 3))  # (bs,85,80,80)-->(bs,80,85,80)         output = P.Transpose()(output, (0, 1, 3, 2))  # (bs,80,85,80)--->(bs, 80, 80, 85)         output = P.Reshape()(output, (batch_size, 1 * grid_size[0] * grid_size[1], -1))  # bs, 6400, 85         grid = P.Reshape()(grid, (1, -1, 2))  # grid(1, 6400, 2)          # reconstruct         output_xy = output[..., :2]         output_xy = (output_xy + grid) * stride         output_wh = output[..., 2:4]         output_wh = P.Exp()(output_wh) * stride         output_other = output[..., 4:]         output_t = P.Concat(axis=-1)([output_xy, output_wh, output_other])         return output_t  # bs, 6400, 85           grid(1, 6400, 2)  #------------------------# # yolox Loss #------------------------# class YOLOLossCell(nn.Cell):     """ yolox with loss cell """      def __init__(self, network=None, config=None):         super(YOLOLossCell, self).__init__()         self.network = network         self.n_candidate_k = config.n_candidate_k         self.on_value = Tensor(1.0, mindspore.float32)         self.off_value = Tensor(0.0, mindspore.float32)         self.depth = config.num_classes          self.unsqueeze = P.ExpandDims()         self.reshape = P.Reshape()         self.one_hot = P.OneHot()         self.zeros = P.ZerosLike()         self.sort_ascending = P.Sort(descending=False)         self.bce_loss = nn.BCEWithLogitsLoss(reduction="none")         self.l1_loss = nn.L1Loss(reduction="none")         self.batch_iter = Tensor(np.arange(0, config.per_batch_size * config.max_gt), mindspore.int32)         self.strides = config.fpn_strides         self.grids = [(config.input_size[0] // _stride) * (config.input_size[1] // _stride) for _stride in                       config.fpn_strides]         self.use_l1 = config.use_l1      def construct(self, img, labels=None, pre_fg_mask=None, is_inbox_and_incenter=None):         """ forward with loss return """         batch_size = P.Shape()(img)[0]         gt_max = P.Shape()(labels)[1]         outputs = self.network(img)  # batch_size, 8400, 85         total_num_anchors = P.Shape()(outputs)[1]         bbox_preds = outputs[:, :, :4]  # batch_size, 8400, 4          obj_preds = outputs[:, :, 4:5]  # batch_size, 8400, 1         cls_preds = outputs[:, :, 5:]  # (batch_size, 8400, 80)          # process label         bbox_true = labels[:, :, 1:]  # (batch_size, gt_max, 4)          gt_classes = F.cast(labels[:, :, 0:1].squeeze(-1), mindspore.int32)         pair_wise_ious = batch_bboxes_iou(bbox_true, bbox_preds, xyxy=False)         pair_wise_ious = pair_wise_ious * pre_fg_mask         pair_wise_iou_loss = -P.Log()(pair_wise_ious + 1e-8) * pre_fg_mask         gt_classes_ = self.one_hot(gt_classes, self.depth, self.on_value, self.off_value)         gt_classes_expaned = ops.repeat_elements(self.unsqueeze(gt_classes_, 2), rep=total_num_anchors, axis=2)         gt_classes_expaned = F.stop_gradient(gt_classes_expaned)          cls_preds_ = P.Sigmoid()(ops.repeat_elements(self.unsqueeze(cls_preds, 1), rep=gt_max, axis=1)) * \                      P.Sigmoid()(                          ops.repeat_elements(self.unsqueeze(obj_preds, 1), rep=gt_max, axis=1)                      )         pair_wise_cls_loss = P.ReduceSum()(             P.BinaryCrossEntropy(reduction="none")(P.Sqrt()(cls_preds_), gt_classes_expaned, None), -1)         pair_wise_cls_loss = pair_wise_cls_loss * pre_fg_mask         cost = pair_wise_cls_loss + 3.0 * pair_wise_iou_loss         punishment_cost = 1000.0 * (1.0 - F.cast(is_inbox_and_incenter, mindspore.float32))         cost = F.cast(cost + punishment_cost, mindspore.float16)         # dynamic k matching         ious_in_boxes_matrix = pair_wise_ious  # (batch_size, gt_max, 8400)         ious_in_boxes_matrix = F.cast(pre_fg_mask * ious_in_boxes_matrix, mindspore.float16)         topk_ious, _ = P.TopK(sorted=True)(ious_in_boxes_matrix, self.n_candidate_k)          dynamic_ks = P.ReduceSum()(topk_ious, 2).astype(mindspore.int32).clip(xmin=1, xmax=total_num_anchors - 1,                                                                               dtype=mindspore.int32)          # (1, batch_size * gt_max, 2)         dynamic_ks_indices = P.Stack(axis=1)((self.batch_iter, dynamic_ks.reshape((-1,))))          dynamic_ks_indices = F.stop_gradient(dynamic_ks_indices)          values, _ = P.TopK(sorted=True)(-cost, self.n_candidate_k)  # b_s , 50, 8400         values = P.Reshape()(-values, (-1, self.n_candidate_k))         max_neg_score = self.unsqueeze(P.GatherNd()(values, dynamic_ks_indices).reshape(batch_size, -1), 2)         pos_mask = F.cast(cost < max_neg_score, mindspore.float32)  # (batch_size, gt_num, 8400)         pos_mask = pre_fg_mask * pos_mask         # ----dynamic_k---- END-----------------------------------------------------------------------------------------         cost_t = cost * pos_mask + (1.0 - pos_mask) * 2000.         min_index, _ = P.ArgMinWithValue(axis=1)(cost_t)         ret_posk = P.Transpose()(nn.OneHot(depth=gt_max, axis=-1)(min_index), (0, 2, 1))         pos_mask = pos_mask * ret_posk         pos_mask = F.stop_gradient(pos_mask)         # AA problem--------------END ----------------------------------------------------------------------------------          # calculate target ---------------------------------------------------------------------------------------------         # Cast precision         pos_mask = F.cast(pos_mask, mindspore.float16)         bbox_true = F.cast(bbox_true, mindspore.float16)         gt_classes_ = F.cast(gt_classes_, mindspore.float16)          reg_target = P.BatchMatMul(transpose_a=True)(pos_mask, bbox_true)  # (batch_size, 8400, 4)         pred_ious_this_matching = self.unsqueeze(P.ReduceSum()((ious_in_boxes_matrix * pos_mask), 1), -1)         cls_target = P.BatchMatMul(transpose_a=True)(pos_mask, gt_classes_)          cls_target = cls_target * pred_ious_this_matching         obj_target = P.ReduceMax()(pos_mask, 1)  # (batch_size, 8400)          # calculate l1_target         reg_target = F.stop_gradient(reg_target)         cls_target = F.stop_gradient(cls_target)         obj_target = F.stop_gradient(obj_target)         bbox_preds = F.cast(bbox_preds, mindspore.float32)         reg_target = F.cast(reg_target, mindspore.float32)         obj_preds = F.cast(obj_preds, mindspore.float32)         obj_target = F.cast(obj_target, mindspore.float32)         cls_preds = F.cast(cls_preds, mindspore.float32)         cls_target = F.cast(cls_target, mindspore.float32)         loss_l1 = 0.0         if self.use_l1:             l1_target = self.get_l1_format(reg_target)             l1_preds = self.get_l1_format(bbox_preds)             l1_target = F.stop_gradient(l1_target)             l1_target = F.cast(l1_target, mindspore.float32)             l1_preds = F.cast(l1_preds, mindspore.float32)             loss_l1 = P.ReduceSum()(self.l1_loss(l1_preds, l1_target), -1) * obj_target             loss_l1 = P.ReduceSum()(loss_l1)         # calculate target -----------END-------------------------------------------------------------------------------         loss_iou = IOUloss()(P.Reshape()(bbox_preds, (-1, 4)), reg_target).reshape(batch_size, -1) * obj_target         loss_iou = P.ReduceSum()(loss_iou)         loss_obj = self.bce_loss(P.Reshape()(obj_preds, (-1, 1)), P.Reshape()(obj_target, (-1, 1)))         loss_obj = P.ReduceSum()(loss_obj)          loss_cls = P.ReduceSum()(self.bce_loss(cls_preds, cls_target), -1) * obj_target         loss_cls = P.ReduceSum()(loss_cls)         loss_all = (5 * loss_iou + loss_cls + loss_obj + loss_l1) / (P.ReduceSum()(obj_target) + 1e-3)         return loss_all      def get_l1_format_single(self, reg_target, stride, eps):         """ calculate L1 loss related """         reg_target = reg_target / stride         reg_target_xy = reg_target[:, :, :2]         reg_target_wh = reg_target[:, :, 2:]         reg_target_wh = P.Log()(reg_target_wh + eps)         return P.Concat(-1)((reg_target_xy, reg_target_wh))      def get_l1_format(self, reg_target, eps=1e-8):         """ calculate L1 loss related """         reg_target_l = reg_target[:, 0:self.grids[0], :]  # (bs, 6400, 4)         reg_target_m = reg_target[:, self.grids[0]:self.grids[1] + self.grids[0], :]  # (bs, 1600, 4)         reg_target_s = reg_target[:, -self.grids[2]:, :]  # (bs, 400, 4)          reg_target_l = self.get_l1_format_single(reg_target_l, self.strides[0], eps)         reg_target_m = self.get_l1_format_single(reg_target_m, self.strides[1], eps)         reg_target_s = self.get_l1_format_single(reg_target_s, self.strides[2], eps)          l1_target = P.Concat(axis=1)([reg_target_l, reg_target_m, reg_target_s])         return l1_target  class IOUloss(nn.Cell):     """ Iou loss """      def __init__(self, reduction="none"):         super(IOUloss, self).__init__()         self.reduction = reduction         self.reshape = P.Reshape()      def construct(self, pred, target):         """ forward """         pred = self.reshape(pred, (-1, 4))         target = self.reshape(target, (-1, 4))         tl = P.Maximum()(pred[:, :2] - pred[:, 2:] / 2, target[:, :2] - target[:, 2:] / 2)         br = P.Minimum()(pred[:, :2] + pred[:, 2:] / 2, target[:, :2] + target[:, 2:] / 2)         area_p = (pred[:, 2:3] * pred[:, 3:4]).squeeze(-1)         area_g = (target[:, 2:3] * target[:, 3:4]).squeeze(-1)         en = F.cast((tl < br), tl.dtype)         en = (en[:, 0:1] * en[:, 1:2]).squeeze(-1)         area_i = br - tl         area_i = (area_i[:, 0:1] * area_i[:, 1:2]).squeeze(-1) * en         area_u = area_p + area_g - area_i          iou = area_i / (area_u + 1e-16)         loss = 1 - iou * iou         if self.reduction == "mean":             loss = loss.mean()         elif self.reduction == "sum":             loss = loss.sum()         return loss  grad_scale = C.MultitypeFuncGraph("grad_scale") reciprocal = P.Reciprocal()  @grad_scale.register("Tensor", "Tensor") def tensor_grad_scale(scale, grad):     return grad * reciprocal(scale)  _grad_overflow = C.MultitypeFuncGraph("_grad_overflow") grad_overflow = P.FloatStatus()  @_grad_overflow.register("Tensor") def _tensor_grad_overflow(grad):     return grad_overflow(grad)  #------------------------# #  ema #------------------------# class TrainOneStepWithEMA(nn.TrainOneStepWithLossScaleCell):     """ Train one step with ema model """      def __init__(self, network, optimizer, scale_sense, ema=True, decay=0.9998, updates=0, moving_name=None,                  ema_moving_weight=None):         super(TrainOneStepWithEMA, self).__init__(network, optimizer, scale_sense)         self.ema = ema         self.moving_name = moving_name         self.ema_moving_weight = ema_moving_weight         if self.ema:             self.ema_weight = self.weights.clone("ema", init='same')             self.decay = decay             self.updates = Parameter(Tensor(updates, mindspore.float32))             self.assign = ops.Assign()             self.ema_moving_parameters()      def ema_moving_parameters(self):         self.moving_name = {}         moving_list = []         idx = 0         for key, param in self.network.parameters_and_names():             if "moving_mean" in key or "moving_variance" in key:                 new_param = param.clone()                 new_param.name = "ema." + param.name                 moving_list.append(new_param)                 self.moving_name["ema." + key] = idx                 idx += 1         self.ema_moving_weight = ParameterTuple(moving_list)      def ema_update(self):         """Update EMA parameters."""         if self.ema:             self.updates += 1             d = self.decay * (1 - ops.Exp()(-self.updates / 2000))             # update trainable parameters             for ema_v, weight in zip(self.ema_weight, self.weights):                 tep_v = ema_v * d                 self.assign(ema_v, (1.0 - d) * weight + tep_v)         return self.updates      # moving_parameter_update is executed inside the callback(EMACallBack)     def moving_parameter_update(self):         if self.ema:             d = (self.decay * (1 - ops.Exp()(-self.updates / 2000))).asnumpy().item()             # update moving mean and moving var             for key, param in self.network.parameters_and_names():                 if "moving_mean" in key or "moving_variance" in key:                     idx = self.moving_name["ema." + key]                     moving_weight = param.asnumpy()                     tep_v = self.ema_moving_weight[idx] * d                     ema_value = (1.0 - d) * moving_weight + tep_v                     self.ema_moving_weight[idx] = ema_value      def construct(self, *inputs):         """ Forward """         weights = self.weights         loss = self.network(*inputs)         scaling_sens = self.scale_sense          status, scaling_sens = self.start_overflow_check(loss, scaling_sens)          scaling_sens_filled = C.ones_like(loss) * F.cast(scaling_sens, F.dtype(loss))         grads = self.grad(self.network, weights)(*inputs, scaling_sens_filled)         grads = self.hyper_map(F.partial(grad_scale, scaling_sens), grads)         # apply grad reducer on grads         grads = self.grad_reducer(grads)         self.ema_update()          # get the overflow buffer         cond = self.get_overflow_status(status, grads)         overflow = self.process_loss_scale(cond)         # if there is no overflow, do optimize         if not overflow:             loss = F.depend(loss, self.optimizer(grads))         return loss, cond, scaling_sens 3.9 设备函数 针对平台设备的相关函数 #------------------------# # device adapter #------------------------# def local_adp_get_device_id():     device_id = os.getenv('DEVICE_ID', '0')     return int(device_id)  def local_adp_get_device_num():     device_num = os.getenv('RANK_SIZE', '1')     return int(device_num)  def local_adp_get_rank_id():     global_rank_id = os.getenv('RANK_ID', '0')     return int(global_rank_id)  def local_adp_get_job_id():     return "Local Job"  def moxing_adp_get_device_id():     device_id = os.getenv('DEVICE_ID', '0')     return int(device_id)  def moxing_adp_get_device_num():     device_num = os.getenv('RANK_SIZE', '1')     return int(device_num)  def moxing_adp_get_rank_id():     global_rank_id = os.getenv('RANK_ID', '0')     return int(global_rank_id)  def moxing_adp_get_job_id():     job_id = os.getenv('JOB_ID')     job_id = job_id if job_id != "" else "default"     return job_id  def sync_data(from_path, to_path):     """     Download data from remote obs to local directory if the first url is remote url and the second one is local path     Upload data from local directory to remote obs in contrast.     """     import moxing as mox     global _global_sync_count     sync_lock = "/tmp/copy_sync.lock" + str(_global_sync_count)     _global_sync_count += 1      # Each server contains 8 devices as most.     if get_device_id() % min(get_device_num(), 8) == 0 and not os.path.exists(sync_lock):         print("from path: ", from_path)         print("to path: ", to_path)         mox.file.copy_parallel(from_path, to_path)         print("===finish data synchronization===")         try:             os.mknod(sync_lock)         except IOError:             pass         print("===save flag===")      while True:         if os.path.exists(sync_lock):             break         time.sleep(1)      print("Finish sync data from {} to {}.".format(from_path, to_path))  def moxing_wrapper(pre_process=None, post_process=None):     """     Moxing wrapper to download dataset and upload outputs.     """     def wrapper(run_func):         @functools.wraps(run_func)         def wrapped_func(*args, **kwargs):             # Download data from data_url             if config.enable_modelarts:                 if config.data_url:                     sync_data(config.data_url, config.data_path)                     print("Dataset downloaded: ", os.listdir(config.data_path))                 if config.checkpoint_url:                     sync_data(config.checkpoint_url, config.load_path)                     print("Preload downloaded: ", os.listdir(config.load_path))                 if config.train_url:                     sync_data(config.train_url, config.output_path)                     print("Workspace downloaded: ", os.listdir(config.output_path))                  context.set_context(save_graphs_path=os.path.join(config.output_path, str(get_rank_id())))                 config.device_num = get_device_num()                 config.device_id = get_device_id()                 if not os.path.exists(config.output_path):                     os.makedirs(config.output_path)                  if pre_process:                     pre_process()              # Run the main function             run_func(*args, **kwargs)              # Upload data to train_url             if config.enable_modelarts:                 if post_process:                     post_process()                  if config.train_url:                     print("Start to copy output directory")                     sync_data(config.output_path, config.train_url)         return wrapped_func     return wrapper  if config.enable_modelarts:     get_device_id = moxing_adp_get_device_id     get_device_num = moxing_adp_get_device_num     get_rank_id = moxing_adp_get_rank_id     get_job_id = moxing_adp_get_job_id else:     get_device_id = local_adp_get_device_id     get_device_num = local_adp_get_device_num     get_rank_id = local_adp_get_rank_id     get_job_id = local_adp_get_job_id  
  • [其他] restnet50
    #数据加载和准备 from download import download  url = "https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/notebook/datasets/cifar-10-binary.tar.gz"  download(url, "./datasets-cifar10-bin", kind="tar.gz", replace=True) #数据加载 import mindspore as ms#将MindSpore框架导入并重命名为ms,以便在代码中使用简短的别名来引用MindSpore的功能。 import mindspore.dataset as ds#入MindSpore中的数据集模块,用于处理和管理数据集。 import mindspore.dataset.vision as vision #入MindSpore中用于处理视觉数据的模块,例如图像数据的加载和预处理。 import mindspore.dataset.transforms as transforms #导入MindSpore中的数据转换模块,用于对数据集进行各种转换和处理操作,如数据增强、标准化等。 from mindspore import dtype as mstype#从MindSpore中导入数据类型(dtype)并将其重命名为mstype,用于指定张量和数组的数据类型 data_dir = "./datasets-cifar10-bin/cifar-10-batches-bin"  # 数据集根目录 batch_size = 256  # 批量大小 image_size = 32  # 训练图像空间大小 workers = 4  # 并行线程个数 num_classes = 10  # 分类数量  def create_dataset_cifar10(dataset_dir, usage, resize, batch_size, workers): #函数:定义了一个函数来创建CIFAR-10数据集,接收参数包括数据集目录、用途、图像大小、批量大小和线程数     data_set = ds.Cifar10Dataset(dataset_dir=dataset_dir,                                  usage=usage,                                  num_parallel_workers=workers,                                  shuffle=True) #使用MindSpore的Cifar10Dataset类创建CIFAR-10数据集,指定数据集目录、用途、线程数和是否打乱数据。     trans = []#定义了一个数据增强操作的列表。     if usage == "train": #如果数据集用途是训练,则执行以下操作。         trans += [        #将随机裁剪和水平翻转等操作添加到数据增强操作列表中。             vision.RandomCrop((32, 32), (4, 4, 4, 4)),             vision.RandomHorizontalFlip(prob=0.5)         ]      trans += [             #将缩放、归一化和通道转换等操作添加到数据增强操作列表中。         vision.Resize(resize),         vision.Rescale(1.0 / 255.0, 0.0),         vision.Normalize([0.4914, 0.4822, 0.4465], [0.2023, 0.1994, 0.2010]),         vision.HWC2CHW()     ]      target_trans = transforms.TypeCast(mstype.int32)   #定义一个目标数据类型转换操作,将标签转换为int32类型。      # 数据映射操作,对图像进行处理     data_set = data_set.map(operations=trans,                             input_columns='image',                             num_parallel_workers=workers)     #将数据集映射到目标数据类型转换操作上,对标签进行处理。     data_set = data_set.map(operations=target_trans,                             input_columns='label',                             num_parallel_workers=workers)      # 批量操作     data_set = data_set.batch(batch_size)      return data_set  # 获取处理后的训练与测试数据集 #使用create_dataset_cifar10函数创建训练数据集。 dataset_train = create_dataset_cifar10(dataset_dir=data_dir,                                        usage="train",                                        resize=image_size,                                        batch_size=batch_size,                                        workers=workers) #获取训练数据集的大小 step_size_train = dataset_train.get_dataset_size() #使用create_dataset_cifar10函数创建测试数据集。 dataset_val = create_dataset_cifar10(dataset_dir=data_dir,                                      usage="test",                                      resize=image_size,                                      batch_size=batch_size,                                      workers=workers) #获取验证数据集的大小,以便在模型评估阶段使用。 step_size_val = dataset_val.get_dataset_size() #对数据进行可视化 import matplotlib.pyplot as plt import numpy as np  data_iter = next(dataset_train.create_dict_iterator())  images = data_iter["image"].asnumpy() labels = data_iter["label"].asnumpy() print(f"Image shape: {images.shape}, Label shape: {labels.shape}")  # 训练数据集中,前六张图片所对应的标签 print(f"Labels: {labels[:6]}")  classes = []  with open(data_dir + "/batches.meta.txt", "r") as f:     for line in f:         line = line.rstrip()         if line:             classes.append(line)  # 训练数据集的前六张图片 plt.figure() for i in range(6):     plt.subplot(2, 3, i + 1)     image_trans = np.transpose(images[i], (1, 2, 0))#对图像数据进行转置操作,将通道维度移动到最后。     mean = np.array([0.4914, 0.4822, 0.4465])#定义图像均值     std = np.array([0.2023, 0.1994, 0.2010])#定义图像标准差     image_trans = std * image_trans + mean#对图像进行反归一化操作     image_trans = np.clip(image_trans, 0, 1)#将图像像素值限制在0到1之间     plt.title(f"{classes[labels[i]]}")#设置当前子图的标题为对应标签的类别信息     plt.imshow(image_trans)#在子图中显示处理后的图像     plt.axis("off")#关闭坐标轴显示 plt.show()#关闭坐标轴显示 #构建网络构建残差网络结构残差网络结构图如下图所示,残差网络由两个分支构成:一个主分支,一个shortcuts(图中弧线表示)。主分支通过堆叠一系列的卷积操作得到,shotcuts从输入直接到输出,主分支输出的特征矩阵𝐹(𝑥)�(�)加上shortcuts输出的特征矩阵𝑥�得到𝐹(𝑥)+𝑥�(�)+�,通过Relu激活函数后即为残差网络最后的输出。如下代码定义ResidualBlockBase类实现Building Block结构。 from typing import Type, Union, List, Optional#导入了需要用到的类型提示模块,用于指定函数参数和返回值的类型。 import mindspore.nn as nn#导入MindSpore深度学习框架中的神经网络模块nn,用于构建神经网络模型。 from mindspore.common.initializer import Normal#从MindSpore深度学习框架的初始化模块中导入了Normal类,用于参数初始化。  # 初始化卷积层与BatchNorm的参数 weight_init = Normal(mean=0, sigma=0.02)#创建一个正态分布的参数初始化对象,平均值为0,标准差为0.02 gamma_init = Normal(mean=1, sigma=0.02)#创建另一个正态分布的参数初始化对象,用于初始化BatchNorm层中的gamma参数。  class ResidualBlockBase(nn.Cell): #表示这是一个神经网络模型的组件。     expansion: int = 1  # 最后一个卷积核数量与第一个卷积核数量相等      def __init__(self, in_channel: int, out_channel: int,                  stride: int = 1, norm: Optional[nn.Cell] = None,                  down_sample: Optional[nn.Cell] = None) -> None:  #定义了初始化函数__init__,接受输入通道数in_channel、                                                                     #输出通道数out_channel、步幅stride、归一化norm和下采样down_sample等参数,并且没有返回值。         super(ResidualBlockBase, self).__init__()   #调用父类nn.Cell的初始化函数,确保正确地初始化继承的属性。         if not norm:  #根据是否传入归一化参数norm,选择是否使用BatchNorm2d归一化层             self.norm = nn.BatchNorm2d(out_channel)         else:             self.norm = norm          self.conv1 = nn.Conv2d(in_channel, out_channel,                                kernel_size=3, stride=stride,                                weight_init=weight_init)#创建一个2维卷积层conv1,指定输入通道数、                                                         #输出通道数、卷积核大小、步幅和参数初始化方式。         self.conv2 = nn.Conv2d(in_channel, out_channel,                                kernel_size=3, weight_init=weight_init)#创建另一个2维卷积层conv2,指定输入通道数、                                                                         #输出通道数、卷积核大小和参数初始化方式。         self.relu = nn.ReLU()#创建一个ReLU激活函数实例relu。         self.down_sample = down_sample #将传入的下采样函数赋值给成员变量down_sample,如果没有传入则为None。      def construct(self, x):#用于定义ResidualBlockBase的前向传播逻辑,接受输入x作为参数         """ResidualBlockBase construct."""         identity = x  # shortcuts分支          out = self.conv1(x)  # 主分支第一层:3*3卷积层  使用conv1进行卷积操作,得到输出out。         out = self.norm(out) #对输出out进行归一化操作。         out = self.relu(out) #对输出out进行ReLU激活函数操作         out = self.conv2(out)  # 主分支第二层:3*3卷积层 使用conv2进行卷积操作,得到输出out。         out = self.norm(out)   # 再次对输出out进行归一化操作          if self.down_sample is not None:  #如果存在下采样函数,对输入x进行下采样操作,并将结果赋值给identity。             identity = self.down_sample(x)         out += identity  # 输出为主分支与shortcuts之和         out = self.relu(out)  #对相加后的输出进行ReLU激活函数操作。          return out #如下代码定义ResidualBlock类实现Bottleneck结构。 class ResidualBlock(nn.Cell):#定义了一个名为ResidualBlock的类,继承自nn.Cell,表示这是一个神经网络模型的组件。     expansion = 4  # 最后一个卷积核的数量是第一个卷积核数量的4倍      def __init__(self, in_channel: int, out_channel: int,                  stride: int = 1, down_sample: Optional[nn.Cell] = None) -> None:           #定义了初始化函数__init__,         #接受输入通道数in_channel、输出通道数out_channel、步幅stride和下采样down_sample等参数,并且没有返回值。          super(ResidualBlock, self).__init__()#调用父类nn.Cell的初始化函数,确保正确地初始化继承的属性。          self.conv1 = nn.Conv2d(in_channel, out_channel,                                kernel_size=1, weight_init=weight_init)         #创建一个2维卷积层conv1,指定输入通道数in_channel、         #输出通道数out_channel、卷积核大小为1,并使用weight_init进行参数初始化。         self.norm1 = nn.BatchNorm2d(out_channel)         #创建一个BatchNorm2d归一化层norm1,指定输入通道数为out_channel。         self.conv2 = nn.Conv2d(out_channel, out_channel,                                kernel_size=3, stride=stride,                                weight_init=weight_init)         #创建一个2维卷积层conv2,指定输入通道数和输出通道数都为out_channel,         #卷积核大小为3,并且可以通过stride参数设置步幅。         self.norm2 = nn.BatchNorm2d(out_channel)         #创建一个BatchNorm2d归一化层norm2,指定输入通道数为out_channel。         self.conv3 = nn.Conv2d(out_channel, out_channel * self.expansion,                                kernel_size=1, weight_init=weight_init)         #创建一个2维卷积层conv3,指定输入通道数为out_channel,         #输出通道数为out_channel * self.expansion(即4倍),卷积核大小为1。         self.norm3 = nn.BatchNorm2d(out_channel * self.expansion)         #创建一个BatchNorm2d归一化层norm3,指定输入通道数为out_channel * self.expansion。         self.relu = nn.ReLU()#创建一个ReLU激活函数实例rel         self.down_sample = down_sample#将传入的下采样函数赋值给成员变量down_sample,如果没有传入则为None。      def construct(self, x): #定义了construct方法,用于定义ResidualBlock的前向传播逻辑,接受输入x作为参数。          identity = x  # shortscuts分支          out = self.conv1(x)  # 主分支第一层:1*1卷积层使用conv1进行卷积操作,得到输出out。         out = self.norm1(out)#对输出out进行归一化操作         out = self.relu(out)#对输出out进行ReLU激活函数操作         out = self.conv2(out)  # 主分支第二层:3*3卷积层 使用conv2进行卷积操作,得到输出out。         out = self.norm2(out)#使用conv2进行卷积操作,得到输出out。         out = self.relu(out)#对输出out进行ReLU激活函数操作。         out = self.conv3(out)  # 主分支第三层:1*1卷积层 使用conv3进行卷积操作,得到输出out。         out = self.norm3(out)#对输出out进行归一化操作。          if self.down_sample is not None:             identity = self.down_sample(x) #如果存在下采样函数,对输入x进行下采样操作,并将结果赋值给identity。          out += identity  # 输出为主分支与shortcuts之和  将主分支的输出与shortcuts分支的输出相加。         out = self.relu(out)  #对相加后的输出进行ReLU激活函数操作。          return out #构建ResNet50网络 def make_layer(last_out_channel, block: Type[Union[ResidualBlockBase, ResidualBlock]],                channel: int, block_nums: int, stride: int = 1):     ##定义了一个名为make_layer的函数,接受输入参数last_out_channel(上一层的输出通道数)、     #zzblock(残差块的类型)、channel(通道数)、block_nums(块的数量)和stride(步幅),并且没有返回值。     down_sample = None  # shortcuts分支      if stride != 1 or last_out_channel != channel * block.expansion:         #判断条件,如果步幅不为1或者上一层的输出通道数不等于channel * block.expansion,进入条件语句块。         down_sample = nn.SequentialCell([             nn.Conv2d(last_out_channel, channel * block.expansion,                       kernel_size=1, stride=stride, weight_init=weight_init),             nn.BatchNorm2d(channel * block.expansion, gamma_init=gamma_init)         ])         #如果满足条件,创建一个下采样模块down_sample,使用Conv2d和BatchNorm2d构建,用于调整维度匹配。     layers = [] #初始化一个空列表layers,用于存储构建的残差块。     layers.append(block(last_out_channel, channel, stride=stride, down_sample=down_sample))         #将第一个残差块添加到layers列表中,传入参数last_out_channel、channel、stride和down_sample。     in_channel = channel * block.expansion #计算下一层的输入通道数,用于堆叠残差网络。     # 堆叠残差网络     for _ in range(1, block_nums): #循环block_nums次,用于堆叠多个残差块。          layers.append(block(in_channel, channel)) #在循环中,将新的残差块添加到layers列表中,传入参数in_channel和channel。      return nn.SequentialCell(layers) #将layers列表中的残差块构建成一个SequentialCell,并返回作为整个层的输出。 #如下示例代码实现ResNet50模型的构建,通过用调函数resnet50即可构建ResNet50模型,函数resnet50参数如下:num_classes:分类的类别数,默认类别数为1000。pretrained:下载对应的训练模型,并加载预训练模型中的参数到网络中。 from mindspore import load_checkpoint, load_param_into_net #从MindSpore库中导入load_checkpoint和load_param_into_net函数,用于加载模型参数到网络中。   class ResNet(nn.Cell): #定义一个名为ResNet的类,继承自nn.Cell,表示这是一个神经网络模型。     def __init__(self, block: Type[Union[ResidualBlockBase, ResidualBlock]],                  layer_nums: List[int], num_classes: int, input_channel: int) -> None:           #定义ResNet类的初始化方法,接受参数block(残差块类型)、layer_nums(各层残差块数量列表)、         #num_classes(分类类别数)、input_channel(输入通道数),并且没有返回值。         super(ResNet, self).__init__() #调用父类nn.Cell的初始化方法。          self.relu = nn.ReLU()         # 第一个卷积层,输入channel为3(彩色图像),输出channel为64         self.conv1 = nn.Conv2d(3, 64, kernel_size=7, stride=2, weight_init=weight_init)         self.norm = nn.BatchNorm2d(64)         # 最大池化层,缩小图片的尺寸         self.max_pool = nn.MaxPool2d(kernel_size=3, stride=2, pad_mode='same')         #定义一个最大池化层,用于下采样特征图,参数设置为3x3的池化核,步幅为2,填充模式为'same'。         # 各个残差网络结构块定义         self.layer1 = make_layer(64, block, 64, layer_nums[0])         self.layer2 = make_layer(64 * block.expansion, block, 128, layer_nums[1], stride=2)         self.layer3 = make_layer(128 * block.expansion, block, 256, layer_nums[2], stride=2)         self.layer4 = make_layer(256 * block.expansion, block, 512, layer_nums[3], stride=2)         # 平均池化层         self.avg_pool = nn.AvgPool2d()         # flattern层         self.flatten = nn.Flatten()         # 全连接层         self.fc = nn.Dense(in_channels=input_channel, out_channels=num_classes)      def construct(self, x):  #定义了网络的构建方法construct,接受输入x作为参数。           x = self.conv1(x)         x = self.norm(x)         x = self.relu(x)         x = self.max_pool(x)          x = self.layer1(x)         x = self.layer2(x)         x = self.layer3(x)         x = self.layer4(x)          x = self.avg_pool(x)         x = self.flatten(x)         x = self.fc(x)          return x  def _resnet(model_url: str, block: Type[Union[ResidualBlockBase, ResidualBlock]],             layers: List[int], num_classes: int, pretrained: bool, pretrained_ckpt: str,             input_channel: int):     model = ResNet(block, layers, num_classes, input_channel)      if pretrained:         # 加载预训练模型         download(url=model_url, path=pretrained_ckpt, replace=True)         param_dict = load_checkpoint(pretrained_ckpt)         load_param_into_net(model, param_dict)      return model  -------------------------------------------------------------------------------------------------def resnet50(num_classes: int = 1000, pretrained: bool = False):     """ResNet50模型"""     resnet50_url = "https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/notebook/models/application/resnet50_224_new.ckpt"     resnet50_ckpt = "./LoadPretrainedModel/resnet50_224_new.ckpt"     return _resnet(resnet50_url, ResidualBlock, [3, 4, 6, 3], num_classes,                    pretrained, resnet50_ckpt, 2048) #模型训练与评估 # 定义ResNet50网络 network = resnet50(pretrained=True)  # 全连接层输入层的大小 in_channel = network.fc.in_channels fc = nn.Dense(in_channels=in_channel, out_channels=10) # 重置全连接层 network.fc = fc  # 设置学习率 num_epochs = 5 lr = nn.cosine_decay_lr(min_lr=0.00001, max_lr=0.001, total_step=step_size_train * num_epochs,                         step_per_epoch=step_size_train, decay_epoch=num_epochs) # 定义优化器和损失函数 opt = nn.Momentum(params=network.trainable_params(), learning_rate=lr, momentum=0.9) loss_fn = nn.SoftmaxCrossEntropyWithLogits(sparse=True, reduction='mean')  def forward_fn(inputs, targets):     logits = network(inputs)     loss = loss_fn(logits, targets)     return loss  grad_fn = ms.value_and_grad(forward_fn, None, opt.parameters)  def train_step(inputs, targets):     loss, grads = grad_fn(inputs, targets)     opt(grads)     return loss import os # 创建迭代器 data_loader_train = dataset_train.create_tuple_iterator(num_epochs=num_epochs) data_loader_val = dataset_val.create_tuple_iterator(num_epochs=num_epochs) # 最佳模型存储路径 best_acc = 0 best_ckpt_dir = "./BestCheckpoint" best_ckpt_path = "./BestCheckpoint/resnet50-best.ckpt" if not os.path.exists(best_ckpt_dir):     os.mkdir(best_ckpt_dir) import mindspore.ops as ops  def train(data_loader, epoch):     """模型训练"""     losses = []     network.set_train(True)      for i, (images, labels) in enumerate(data_loader):         loss = train_step(images, labels)         if i % 100 == 0 or i == step_size_train - 1:             print('Epoch: [%3d/%3d], Steps: [%3d/%3d], Train Loss: [%5.3f]' %                   (epoch + 1, num_epochs, i + 1, step_size_train, loss))         losses.append(loss)      return sum(losses) / len(losses)  def evaluate(data_loader):     """模型验证"""     network.set_train(False)      correct_num = 0.0  # 预测正确个数     total_num = 0.0  # 预测总数      for images, labels in data_loader:         logits = network(images)         pred = logits.argmax(axis=1)  # 预测结果         correct = ops.equal(pred, labels).reshape((-1, ))         correct_num += correct.sum().asnumpy()         total_num += correct.shape[0]      acc = correct_num / total_num  # 准确率      return acc  # 开始循环训练 print("Start Training Loop ...")  for epoch in range(num_epochs):     curr_loss = train(data_loader_train, epoch)     curr_acc = evaluate(data_loader_val)      print("-" * 50)     print("Epoch: [%3d/%3d], Average Train Loss: [%5.3f], Accuracy: [%5.3f]" % (         epoch+1, num_epochs, curr_loss, curr_acc     ))     print("-" * 50)      # 保存当前预测准确率最高的模型     if curr_acc > best_acc:         best_acc = curr_acc         ms.save_checkpoint(network, best_ckpt_path)  print("=" * 80) print(f"End of validation the best Accuracy is: {best_acc: 5.3f}, "       f"save the best ckpt file in {best_ckpt_path}", flush=True) #可视化模型预测 import matplotlib.pyplot as plt  def visualize_model(best_ckpt_path, dataset_val):     num_class = 10  # 对狼和狗图像进行二分类     net = resnet50(num_class)     # 加载模型参数     param_dict = ms.load_checkpoint(best_ckpt_path)     ms.load_param_into_net(net, param_dict)     # 加载验证集的数据进行验证     data = next(dataset_val.create_dict_iterator())     images = data["image"]     labels = data["label"]     # 预测图像类别     output = net(data['image'])     pred = np.argmax(output.asnumpy(), axis=1)      # 图像分类     classes = []      with open(data_dir + "/batches.meta.txt", "r") as f:         for line in f:             line = line.rstrip()             if line:                 classes.append(line)      # 显示图像及图像的预测值     plt.figure()     for i in range(6):         plt.subplot(2, 3, i + 1)         # 若预测正确,显示为蓝色;若预测错误,显示为红色         color = 'blue' if pred[i] == labels.asnumpy()[i] else 'red'         plt.title('predict:{}'.format(classes[pred[i]]), color=color)         picture_show = np.transpose(images.asnumpy()[i], (1, 2, 0))         mean = np.array([0.4914, 0.4822, 0.4465])         std = np.array([0.2023, 0.1994, 0.2010])         picture_show = std * picture_show + mean         picture_show = np.clip(picture_show, 0, 1)         plt.imshow(picture_show)         plt.axis('off')      plt.show()  # 使用测试数据集进行验证 visualize_model(best_ckpt_path=best_ckpt_path, dataset_val=dataset_val) 
  • [问题求助] 如何把在jupyter上写的程序图像重建程序弄到开发板上atlas200DK跑啊
    我们自己写了一个unet模型的程序,怎么将它弄到atlas200DK开发板上跑啊,已经完成了制卡,修改ip地址的步骤了。谢谢各位大神了
  • [互动交流] 图片验证码怎么提取啊?大佬救命
    怎么识别该类图像验证码??
  • 有能力的加
    曾拿过这类比赛奖项,做过硬件Ascend一些项目,能够结合起来,来的加
  • [互动交流] 华为图像内容审核中文本检测的词库是哪里的?
    类似于对于输入的文本内容进行敏感词审核,想知道华为的敏感词库是怎么维护的?都有哪些敏感词,是不是会自学习? 另外是否可以对这个词库进行扩充?
  • [技术干货] AIGC与AidLux互联应用—Aidlux端AIGC测评
    本帖源于AidLux面向众多开发者的AIGC训练营,目的在于实现使用stablediffusion生成图片传输到AidLux端实现目标检测。分享部分传输检测代码及其实现视频如下:视频链接:AIGC与AidLux互联应用—Aidlux端AIGC测评_哔哩哔哩_bilibiliimport socketimport cv2import numpy as npimport timeimport sys ### 本代码主要是客户端代码,aidlux上的Socket_fuwuduan.py是匹配的服务端代码,当服务端代码启动时,由本代码读取一张图片,推送过去 def recvall(sock, count): buf = b'' # buf是一个byte类型 while count: newbuf = sock.recv(count) if not newbuf: return None buf += newbuf count -= len(newbuf) return buf def SendAIGC(): # 建立sock连接 # address要连接的aidlux服务器IP地址和端口号 address = ('192.168.137.116', 9023) try: # 建立socket对象 # socket.AF_INET:服务器之间网络通信 # socket.SOCK_STREAM:流式socket , for TCP sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 开启连接 sock.connect(address) except socket.error as msg: print(msg) sys.exit(1) ###########传送AIGC图片################# ## 如果本地没有GPU if 1: frame = cv2.imread("car.png") # # 压缩参数,后面cv2.imencode将会用到,对于jpeg来说,15代表图像质量,越高代表图像质量越好为 0-100,默认95 encode_param = [int(cv2.IMWRITE_JPEG_QUALITY), 95] # cv2.imencode将图片格式转换(编码)成流数据,赋值到内存缓存中;主要用于图像数据格式的压缩,方便网络传输 # '.jpg'表示将图片按照jpg格式编码。 result, imgencode = cv2.imencode('.jpg', frame, encode_param) # 建立矩阵 data = np.array(imgencode) # 将numpy矩阵转换成字符形式,以便在网络中传输 stringData = data.tostring() # 先发送要发送的数据的长度 # ljust() 方法返回一个原字符串左对齐,并使用空格填充至指定长度的新字符串 sock.send(str.encode(str(len(stringData)).ljust(16))) # 发送数据 sock.send(stringData) ### 如果本地有GPU # if 0: # ### 本地生成AIGC图片 ### # ## 添加AIGC代码 ## # ##################### # frame = cv2.imread("car.png") # # # 压缩参数,后面cv2.imencode将会用到,对于jpeg来说,15代表图像质量,越高代表图像质量越好为 0-100,默认95 # encode_param = [int(cv2.IMWRITE_JPEG_QUALITY), 95] # # cv2.imencode将图片格式转换(编码)成流数据,赋值到内存缓存中;主要用于图像数据格式的压缩,方便网络传输 # # '.jpg'表示将图片按照jpg格式编码。 # result, imgencode = cv2.imencode('.jpg', frame, encode_param) # # 建立矩阵 # data = np.array(imgencode) # # 将numpy矩阵转换成字符形式,以便在网络中传输 # stringData = data.tostring() # # 先发送要发送的数据的长度 # # ljust() 方法返回一个原字符串左对齐,并使用空格填充至指定长度的新字符串 # sock.send(str.encode(str(len(stringData)).ljust(16))) # # 发送数据 # sock.send(stringData) # 读取服务器返回值 receive = sock.recv(1000) receive1 = sock.recv(1000) receive2 = sock.recv(1000) i = 0 if len(receive): print("图片发送成功") print("检测类别及其数目:") print(str(receive, encoding='utf-8'),str(receive1, encoding='utf-8')) # print(str(receive2, encoding='utf-8')) ### 之前接受的帧率数据,现在换成image流数据 sock.close() if __name__ == '__main__': SendAIGC()该部分代码用于传输生成的图片到Aidlux端,并且接受返回的回馈信息。
总条数:78 到第
上滑加载中