def __init__(self, n_classes, inference): super().__init__() self.inference = inference self.conv1 = Conv_Bn_Activation(512, 512, 3, 1, 'leaky') self.conv2 = Conv_Bn_Activation(512, 256, 1, 1, 'leaky') self.conv3 = Conv_Bn_Activation(256, 512, 3, 1, 'leaky') self.conv4 = Conv_Bn_Activation(512, (4 + 1 + n_classes) * 3, 1, 1, 'linear', bn=False, bias=True) self.yolo1 = YoloLayer( anchor_mask=[3, 4, 5], num_classes=n_classes, anchors=[10, 14, 23, 27, 37, 58, 81, 82, 135, 169, 344, 319], num_anchors=6, stride=32) self.conv5 = Conv_Bn_Activation(256, 128, 1, 1, 'leaky') self.upsample1 = Upsample() self.conv6 = Conv_Bn_Activation(384, 256, 3, 1, 'leaky') self.conv7 = Conv_Bn_Activation(256, (4 + 1 + n_classes) * 3, 1, 1, 'linear', bn=False, bias=True) self.yolo2 = YoloLayer( anchor_mask=[1, 2, 3], num_classes=n_classes, anchors=[10, 14, 23, 27, 37, 58, 81, 82, 135, 169, 344, 319], num_anchors=6, stride=16)
def __init__(self, output_ch, n_classes, inference=False): super().__init__() self.inference = inference self.conv1 = Conv_Bn_Activation(128, 256, 3, 1, 'leaky') self.conv2 = Conv_Bn_Activation(256, output_ch, 1, 1, 'linear', bn=False, bias=True) self.yolo1 = YoloLayer( anchor_mask=[0, 1, 2], num_classes=n_classes, anchors=[12, 16, 19, 36, 40, 28, 36, 75, 76, 55, 72, 146, 142, 110, 192, 243, 459, 401], num_anchors=9, stride=8 ) # R -4 self.conv3 = Conv_Bn_Activation(128, 256, 3, 2, 'leaky') # R -1 -16 self.conv4 = Conv_Bn_Activation(512, 256, 1, 1, 'leaky') self.conv5 = Conv_Bn_Activation(256, 512, 3, 1, 'leaky') self.conv6 = Conv_Bn_Activation(512, 256, 1, 1, 'leaky') self.conv7 = Conv_Bn_Activation(256, 512, 3, 1, 'leaky') self.conv8 = Conv_Bn_Activation(512, 256, 1, 1, 'leaky') self.conv9 = Conv_Bn_Activation(256, 512, 3, 1, 'leaky') self.conv10 = Conv_Bn_Activation(512, output_ch, 1, 1, 'linear', bn=False, bias=True) self.yolo2 = YoloLayer( anchor_mask=[3, 4, 5], num_classes=n_classes, anchors=[12, 16, 19, 36, 40, 28, 36, 75, 76, 55, 72, 146, 142, 110, 192, 243, 459, 401], num_anchors=9, stride=16 ) # R -4 self.conv11 = Conv_Bn_Activation(256, 512, 3, 2, 'leaky') # R -1 -37 self.conv12 = Conv_Bn_Activation(1024, 512, 1, 1, 'leaky') self.conv13 = Conv_Bn_Activation(512, 1024, 3, 1, 'leaky') self.conv14 = Conv_Bn_Activation(1024, 512, 1, 1, 'leaky') self.conv15 = Conv_Bn_Activation(512, 1024, 3, 1, 'leaky') self.conv16 = Conv_Bn_Activation(1024, 512, 1, 1, 'leaky') self.conv17 = Conv_Bn_Activation(512, 1024, 3, 1, 'leaky') self.conv18 = Conv_Bn_Activation(1024, output_ch, 1, 1, 'linear', bn=False, bias=True) self.yolo3 = YoloLayer( anchor_mask=[6, 7, 8], num_classes=n_classes, anchors=[12, 16, 19, 36, 40, 28, 36, 75, 76, 55, 72, 146, 142, 110, 192, 243, 459, 401], num_anchors=9, stride=32 )
def create_network(self, blocks): models = nn.ModuleList() prev_filters = 3 out_filters = [] prev_stride = 1 out_strides = [] conv_id = 0 for block in blocks: if block['type'] == 'net': prev_filters = int(block['channels']) continue elif block['type'] == 'convolutional': conv_id = conv_id + 1 batch_normalize = int(block['batch_normalize']) filters = int(block['filters']) kernel_size = int(block['size']) stride = int(block['stride']) is_pad = int(block['pad']) pad = (kernel_size - 1) // 2 if is_pad else 0 activation = block['activation'] model = nn.Sequential() if batch_normalize: model.add_module( 'conv{0}'.format(conv_id), nn.Conv2d(prev_filters, filters, kernel_size, stride, pad, bias=False)) model.add_module('bn{0}'.format(conv_id), nn.BatchNorm2d(filters)) # model.add_module('bn{0}'.format(conv_id), BN2d(filters)) else: model.add_module( 'conv{0}'.format(conv_id), nn.Conv2d(prev_filters, filters, kernel_size, stride, pad)) if activation == 'leaky': model.add_module('leaky{0}'.format(conv_id), nn.LeakyReLU(0.1, inplace=True)) elif activation == 'relu': model.add_module('relu{0}'.format(conv_id), nn.ReLU(inplace=True)) elif activation == 'mish': model.add_module('mish{0}'.format(conv_id), Mish()) else: print("convalution havn't activate {}".format(activation)) prev_filters = filters out_filters.append(prev_filters) prev_stride = stride * prev_stride out_strides.append(prev_stride) models.append(model) elif block['type'] == 'maxpool': pool_size = int(block['size']) stride = int(block['stride']) if stride == 1 and pool_size % 2: # You can use Maxpooldark instead, here is convenient to convert onnx. # Example: [maxpool] size=3 stride=1 model = nn.MaxPool2d(kernel_size=pool_size, stride=stride, padding=pool_size // 2) elif stride == pool_size: # You can use Maxpooldark instead, here is convenient to convert onnx. # Example: [maxpool] size=2 stride=2 model = nn.MaxPool2d(kernel_size=pool_size, stride=stride, padding=0) else: model = MaxPoolDark(pool_size, stride) out_filters.append(prev_filters) prev_stride = stride * prev_stride out_strides.append(prev_stride) models.append(model) elif block['type'] == 'avgpool': model = GlobalAvgPool2d() out_filters.append(prev_filters) models.append(model) elif block['type'] == 'softmax': model = nn.Softmax() out_strides.append(prev_stride) out_filters.append(prev_filters) models.append(model) elif block['type'] == 'cost': if block['_type'] == 'sse': model = nn.MSELoss(size_average=True) elif block['_type'] == 'L1': model = nn.L1Loss(size_average=True) elif block['_type'] == 'smooth': model = nn.SmoothL1Loss(size_average=True) out_filters.append(1) out_strides.append(prev_stride) models.append(model) elif block['type'] == 'reorg': stride = int(block['stride']) prev_filters = stride * stride * prev_filters out_filters.append(prev_filters) prev_stride = prev_stride * stride out_strides.append(prev_stride) models.append(Reorg(stride)) elif block['type'] == 'upsample': stride = int(block['stride']) out_filters.append(prev_filters) prev_stride = prev_stride // stride out_strides.append(prev_stride) models.append(Upsample_expand(stride)) # models.append(Upsample_interpolate(stride)) elif block['type'] == 'route': layers = block['layers'].split(',') ind = len(models) layers = [ int(i) if int(i) > 0 else int(i) + ind for i in layers ] if len(layers) == 1: if 'groups' not in block.keys() or int( block['groups']) == 1: prev_filters = out_filters[layers[0]] prev_stride = out_strides[layers[0]] else: prev_filters = out_filters[layers[0]] // int( block['groups']) prev_stride = out_strides[layers[0]] // int( block['groups']) elif len(layers) == 2: assert (layers[0] == ind - 1 or layers[1] == ind - 1) prev_filters = out_filters[layers[0]] + out_filters[ layers[1]] prev_stride = out_strides[layers[0]] elif len(layers) == 4: assert (layers[0] == ind - 1) prev_filters = out_filters[layers[0]] + out_filters[layers[1]] + out_filters[layers[2]] + \ out_filters[layers[3]] prev_stride = out_strides[layers[0]] else: print("route error!!!") out_filters.append(prev_filters) out_strides.append(prev_stride) models.append(EmptyModule()) elif block['type'] == 'shortcut': ind = len(models) prev_filters = out_filters[ind - 1] out_filters.append(prev_filters) prev_stride = out_strides[ind - 1] out_strides.append(prev_stride) models.append(EmptyModule()) elif block['type'] == 'connected': filters = int(block['output']) if block['activation'] == 'linear': model = nn.Linear(prev_filters, filters) elif block['activation'] == 'leaky': model = nn.Sequential(nn.Linear(prev_filters, filters), nn.LeakyReLU(0.1, inplace=True)) elif block['activation'] == 'relu': model = nn.Sequential(nn.Linear(prev_filters, filters), nn.ReLU(inplace=True)) prev_filters = filters out_filters.append(prev_filters) out_strides.append(prev_stride) models.append(model) elif block['type'] == 'region': loss = RegionLoss() anchors = block['anchors'].split(',') loss.anchors = [float(i) for i in anchors] loss.num_classes = int(block['classes']) loss.num_anchors = int(block['num']) loss.anchor_step = len(loss.anchors) // loss.num_anchors loss.object_scale = float(block['object_scale']) loss.noobject_scale = float(block['noobject_scale']) loss.class_scale = float(block['class_scale']) loss.coord_scale = float(block['coord_scale']) out_filters.append(prev_filters) out_strides.append(prev_stride) models.append(loss) elif block['type'] == 'yolo': yolo_layer = YoloLayer() anchors = block['anchors'].split(',') anchor_mask = block['mask'].split(',') yolo_layer.anchor_mask = [int(i) for i in anchor_mask] yolo_layer.anchors = [float(i) for i in anchors] yolo_layer.num_classes = int(block['classes']) self.num_classes = yolo_layer.num_classes yolo_layer.num_anchors = int(block['num']) yolo_layer.anchor_step = len( yolo_layer.anchors) // yolo_layer.num_anchors yolo_layer.stride = prev_stride yolo_layer.scale_x_y = float(block['scale_x_y']) # yolo_layer.object_scale = float(block['object_scale']) # yolo_layer.noobject_scale = float(block['noobject_scale']) # yolo_layer.class_scale = float(block['class_scale']) # yolo_layer.coord_scale = float(block['coord_scale']) out_filters.append(prev_filters) out_strides.append(prev_stride) models.append(yolo_layer) else: print('unknown type %s' % (block['type'])) return models
def create_network(self, blocks): model = nn.ModuleList() prev_filters = 3 out_filters = [] prev_stride = 1 out_strides = [] conv_id = 0 for block in blocks: if block["type"] == "net": prev_filters = int(block["channels"]) continue elif block["type"] == "convolutional": conv_id += 1 batch_normalize = int(block["batch_normalize"]) filters = int(block["filters"]) is_pad = int(block["pad"]) stride = int(block["stride"]) kernel_size = [ int(x) for x in block["size"].strip().split(",") ] if len( kernel_size ) == 2: # When this happens kernel size must be odd in both dimensions kernel_size = (kernel_size[0], kernel_size[1] ) # pytorch convention H x W pad = ((kernel_size[0] - 1) // 2, (kernel_size[1] - 1) // 2) if is_pad else 0 else: kernel_size = (kernel_size[0], kernel_size[0]) pad = ((kernel_size[0] - 1) // 2 if is_pad else 0 ) # padding is defined as size/2 in yolo wiki activation = block["activation"] # add convolutional layer conv = nn.Sequential() if batch_normalize: conv.add_module( "conv{0}".format(conv_id), nn.Conv2d(prev_filters, filters, kernel_size, stride, pad, bias=False), ) conv.add_module("bn{0}".format(conv_id), nn.BatchNorm2d(filters)) else: conv.add_module( "conv{0}".format(conv_id), nn.Conv2d(prev_filters, filters, kernel_size, stride, pad), ) # add activation function if activation == "leaky": conv.add_module("leaky{0}".format(conv_id), nn.LeakyReLU(0.1, inplace=True)) elif activation == "relu": conv.add_module("relu{0}".format(conv_id), nn.ReLU(inplace=True)) elif activation == "mish": conv.add_module("mish{0}".format(conv_id), Mish()) elif activation == "linear": pass else: print( f'conv{conv_id} activation "{activation}" not recognized' ) # update params prev_filters = filters out_filters.append(prev_filters) prev_stride = stride * prev_stride out_strides.append(prev_stride) model.append(conv) elif block["type"] == "maxpool": pool_size = int(block["size"]) stride = int(block["stride"]) if stride == 1 and pool_size % 2: maxpool = nn.MaxPool2d(kernel_size=pool_size, stride=stride, padding=pool_size // 2) elif stride == pool_size: maxpool = nn.MaxPool2d(kernel_size=pool_size, stride=stride, padding=0) else: maxpool = MaxPoolDark(pool_size, stride) out_filters.append(prev_filters) prev_stride = stride * prev_stride out_strides.append(prev_stride) model.append(maxpool) elif block["type"] == "upsample": stride = int(block["stride"]) out_filters.append(prev_filters) prev_stride = prev_stride // stride out_strides.append(prev_stride) model.append(Upsample_expand(stride)) # model.append(Upsample_interpolate(stride)) elif block["type"] == "route": layers = block["layers"].split(",") ind = len(model) layers = [ int(i) if int(i) > 0 else int(i) + ind for i in layers ] if len(layers) == 1: prev_filters = out_filters[layers[0]] prev_stride = out_strides[layers[0]] elif len(layers) == 2: assert layers[0] == ind - 1 or layers[1] == ind - 1 prev_filters = out_filters[layers[0]] + out_filters[ layers[1]] prev_stride = out_strides[layers[0]] elif len(layers) == 4: assert layers[0] == ind - 1 prev_filters = (out_filters[layers[0]] + out_filters[layers[1]] + out_filters[layers[2]] + out_filters[layers[3]]) prev_stride = out_strides[layers[0]] else: print("route error!!!") out_filters.append(prev_filters) out_strides.append(prev_stride) model.append(EmptyModule()) elif block["type"] == "shortcut": ind = len(model) prev_filters = out_filters[ind - 1] out_filters.append(prev_filters) prev_stride = out_strides[ind - 1] out_strides.append(prev_stride) model.append(EmptyModule()) elif block["type"] == "yolo": if self.model_type == "BEV_grid": # BEV grid layer # TODO: go through this code and remove unneccessary parameters yolo_layer = YoloBEVGridLayer() yolo_layer.num_classes = int(block["classes"]) self.num_classes = yolo_layer.num_classes yolo_layer.num_anchors = self.num_anchors yolo_layer.stride = prev_stride yolo_layer.scale_x_y = float(block["scale_x_y"]) out_filters.append(prev_filters) out_strides.append(prev_stride) model.append(yolo_layer) elif self.model_type == "BEV_flat": # BEV flat layer yolo_layer = YoloBEVFlatLayer() yolo_layer.num_classes = int(block["classes"]) self.num_classes = yolo_layer.num_classes yolo_layer.num_predictors = self.num_predictors yolo_layer.num_anchors = self.num_anchors model.append(yolo_layer) elif self.model_type == "Yolov4": # Classic Yolo layer yolo_layer = YoloLayer() anchors = block["anchors"].split(",") anchor_mask = block["mask"].split(",") yolo_layer.anchor_mask = [int(i) for i in anchor_mask] yolo_layer.anchors = [float(i) for i in anchors] yolo_layer.num_classes = int(block["classes"]) self.num_classes = yolo_layer.num_classes yolo_layer.num_anchors = int(block["num"]) yolo_layer.anchor_step = len( yolo_layer.anchors) // yolo_layer.num_anchors yolo_layer.stride = prev_stride yolo_layer.scale_x_y = float(block["scale_x_y"]) out_filters.append(prev_filters) out_strides.append(prev_stride) model.append(yolo_layer) else: print( "model type not recognized while building yolo layer!") else: print("unknown type %s" % (block["type"])) return model
def create_network(self, blocks): models = nn.ModuleList() # 创建一个空的ModuleList prev_filters = 3 out_filters = [] prev_stride = 1 out_strides = [] conv_id = 0 for block in blocks: if block['type'] == 'net': # 只有一个net prev_filters = int(block['channels']) # 3 continue elif block['type'] == 'convolutional': # 卷积层,yolov4.cfg共有110个卷积层 conv_id = conv_id + 1 # 按顺序将卷积层编号,后面进行模块命名 # 得到该卷积层的各项参数 batch_normalize = int(block['batch_normalize']) filters = int(block['filters']) kernel_size = int(block['size']) stride = int(block['stride']) is_pad = int(block['pad']) # darknet只有两种kernel_size,若kernel_size=1,则pad=0 若kernel_size=3,则pad=1 # 补充:output_size =1+ (input_size+2*padding-kernel_size)/stride pad = (kernel_size - 1) // 2 if is_pad else 0 activation = block['activation'] model = nn.Sequential() # 创建一个空的Sequential # 公式:卷积层=ConvBnAct,有个别卷积层没有BN,有的层没有激活(linear) if batch_normalize: # 有BN,不需要偏置 model.add_module( 'conv{0}'.format(conv_id), nn.Conv2d(prev_filters, filters, kernel_size, stride, pad, bias=False)) model.add_module('bn{0}'.format(conv_id), nn.BatchNorm2d(filters)) # model.add_module('bn{0}'.format(conv_id), BN2d(filters)) else: # 没有BN,需要偏置(nn.Conv2d中的bias默认为True) model.add_module( 'conv{0}'.format(conv_id), nn.Conv2d(prev_filters, filters, kernel_size, stride, pad)) if activation == 'leaky': # inplace表示原地操作,在原变量不存在分支的情况下是没问题的,可以节省内存 model.add_module('leaky{0}'.format(conv_id), nn.LeakyReLU(0.1, inplace=True)) elif activation == 'relu': # yolov4里没有用relu model.add_module('relu{0}'.format(conv_id), nn.ReLU(inplace=True)) elif activation == 'mish': model.add_module('mish{0}'.format(conv_id), Mish()) else: # yolov4里除了leaky和mish,就是linear,表示没有激活层 # 这个打印信息没用,改成空语句pass # print("convolution haven't activate {}".format(activation)) pass prev_filters = filters out_filters.append(prev_filters) prev_stride = stride * prev_stride out_strides.append(prev_stride) models.append(model) elif block['type'] == 'maxpool': # 最大池化层,yolov4.cfg只有3个 # 池化层只有两个参数,核大小和步长 pool_size = int(block['size']) # yolov4三个最大池化层的步长分别为5,9,13 stride = int(block['stride']) if stride == 1 and pool_size % 2: # You can use Maxpooldark instead, here is convenient to convert onnx. # Example: [maxpool] size=3 stride=1 model = nn.MaxPool2d(kernel_size=pool_size, stride=stride, padding=pool_size // 2) elif stride == pool_size: # You can use Maxpooldark instead, here is convenient to convert onnx. # Example: [maxpool] size=2 stride=2 model = nn.MaxPool2d(kernel_size=pool_size, stride=stride, padding=0) else: # yolov4用的都是MaxPoolDark model = MaxPoolDark(pool_size, stride) out_filters.append(prev_filters) prev_stride = stride * prev_stride out_strides.append(prev_stride) models.append(model) elif block['type'] == 'avgpool': # yolov4.cfg里没有avgpool model = GlobalAvgPool2d() out_filters.append(prev_filters) models.append(model) elif block['type'] == 'softmax': # yolov4.cfg里没有softmax model = nn.Softmax() out_strides.append(prev_stride) out_filters.append(prev_filters) models.append(model) elif block['type'] == 'cost': # yolov4.cfg里没有cost if block['_type'] == 'sse': model = nn.MSELoss(reduction='mean') elif block['_type'] == 'L1': model = nn.L1Loss(reduction='mean') elif block['_type'] == 'smooth': model = nn.SmoothL1Loss(reduction='mean') out_filters.append(1) out_strides.append(prev_stride) models.append(model) elif block['type'] == 'reorg': # yolov4.cfg里没有reorg stride = int(block['stride']) prev_filters = stride * stride * prev_filters out_filters.append(prev_filters) prev_stride = prev_stride * stride out_strides.append(prev_stride) models.append(Reorg(stride)) elif block['type'] == 'upsample': # yolov4.cfg里有两个upsample stride = int(block['stride']) out_filters.append(prev_filters) prev_stride = prev_stride // stride out_strides.append(prev_stride) models.append(Upsample_expand(stride)) # Upsample_expand上采样 # models.append(Upsample_interpolate(stride)) elif block['type'] == 'route': # yolo中的一个特殊层,作用是路由和拼接 layers = block['layers'].split(',') ind = len(models) # 如果layers索引大于0,则代表层数,如果小于0,代表从当前层往前减 layers = [ int(i) if int(i) > 0 else int(i) + ind for i in layers ] if len(layers) == 1: # 如果layers只有一个 if 'groups' not in block.keys() or int( block['groups']) == 1: # 对于yolov4.cfg,为True # 获取指定layer的核数量和步长 prev_filters = out_filters[layers[0]] prev_stride = out_strides[layers[0]] else: prev_filters = out_filters[layers[0]] // int( block['groups']) prev_stride = out_strides[layers[0]] // int( block['groups']) elif len(layers) == 2: # 如果layer有两个 # 如果layer有两个,肯定有一个是-1 assert (layers[0] == ind - 1 or layers[1] == ind - 1) # 核数量为两个层的核数量之和 prev_filters = out_filters[layers[0]] + out_filters[ layers[1]] prev_stride = out_strides[layers[0]] elif len(layers) == 4: # 如果layer有4个 # 如果layer有四个,肯定有一个是-1 assert (layers[0] == ind - 1) # 核数量为四个层的核数量之和 prev_filters = out_filters[layers[0]] + out_filters[layers[1]] + out_filters[layers[2]] + \ out_filters[layers[3]] prev_stride = out_strides[layers[0]] else: print("route error!!!") # 设置虚空的核数量和步长,以及用于占位的空层 out_filters.append(prev_filters) out_strides.append(prev_stride) models.append(EmptyModule()) elif block['type'] == 'shortcut': # yolov4里有23个shortcut ind = len(models) # 设置虚空的核数量和步长,以及用于占位的空层 prev_filters = out_filters[ind - 1] out_filters.append(prev_filters) prev_stride = out_strides[ind - 1] out_strides.append(prev_stride) models.append(EmptyModule()) elif block['type'] == 'connected': # yolov4.cfg里没有connected filters = int(block['output']) if block['activation'] == 'linear': model = nn.Linear(prev_filters, filters) elif block['activation'] == 'leaky': model = nn.Sequential(nn.Linear(prev_filters, filters), nn.LeakyReLU(0.1, inplace=True)) elif block['activation'] == 'relu': model = nn.Sequential(nn.Linear(prev_filters, filters), nn.ReLU(inplace=True)) prev_filters = filters out_filters.append(prev_filters) out_strides.append(prev_stride) models.append(model) elif block['type'] == 'region': # yolov4.cfg里没有region loss = RegionLoss() anchors = block['anchors'].split(',') loss.anchors = [float(i) for i in anchors] loss.num_classes = int(block['classes']) loss.num_anchors = int(block['num']) loss.anchor_step = len(loss.anchors) // loss.num_anchors loss.object_scale = float(block['object_scale']) loss.noobject_scale = float(block['noobject_scale']) loss.class_scale = float(block['class_scale']) loss.coord_scale = float(block['coord_scale']) out_filters.append(prev_filters) out_strides.append(prev_stride) models.append(loss) elif block['type'] == 'yolo': # yolov4.cfg里有3个yolo yolo_layer = YoloLayer() anchors = block['anchors'].split(',') anchor_mask = block['mask'].split(',') yolo_layer.anchor_mask = [int(i) for i in anchor_mask] yolo_layer.anchors = [float(i) for i in anchors] yolo_layer.num_classes = int(block['classes']) self.num_classes = yolo_layer.num_classes yolo_layer.num_anchors = int(block['num']) yolo_layer.anchor_step = len( yolo_layer.anchors) // yolo_layer.num_anchors yolo_layer.stride = prev_stride yolo_layer.scale_x_y = float(block['scale_x_y']) # yolo_layer.object_scale = float(block['object_scale']) # yolo_layer.noobject_scale = float(block['noobject_scale']) # yolo_layer.class_scale = float(block['class_scale']) # yolo_layer.coord_scale = float(block['coord_scale']) out_filters.append(prev_filters) out_strides.append(prev_stride) models.append(yolo_layer) else: print('unknown type %s' % (block['type'])) return models
def create_network(self, blocks): """根据 blocks 创建网络models :param blocks: blocks模块配置 :return: nn.ModuleList() """ models = nn.ModuleList() prev_filters = 3 # 前一层 channels个数 out_filters = [] # 所有层(无输入层)的通道数 prev_stride = 1 # 前一层 stride 大小,相对于原始图像大小 out_strides = [] # 所有层(无输入层)的stride大小,相对于原始图像大小 conv_id = 0 # 每一层ID for block in blocks: if block['type'] == 'net': # 网络配置 prev_filters = int(block['channels']) continue elif block['type'] == 'convolutional': # 卷积 conv_id = conv_id + 1 batch_normalize = int(block['batch_normalize']) filters = int(block['filters']) kernel_size = int(block['size']) stride = int(block['stride']) is_pad = int(block['pad']) pad = (kernel_size - 1) // 2 if is_pad else 0 activation = block['activation'] model = nn.Sequential() if batch_normalize: model.add_module( 'conv{0}'.format(conv_id), nn.Conv2d(prev_filters, filters, kernel_size, stride, pad, bias=False)) model.add_module('bn{0}'.format(conv_id), nn.BatchNorm2d(filters)) else: model.add_module( 'conv{0}'.format(conv_id), nn.Conv2d(prev_filters, filters, kernel_size, stride, pad)) if activation == 'leaky': model.add_module('leaky{0}'.format(conv_id), nn.LeakyReLU(0.1, inplace=True)) elif activation == 'relu': model.add_module('relu{0}'.format(conv_id), nn.ReLU(inplace=True)) elif activation == 'mish': model.add_module('mish{0}'.format(conv_id), Mish()) else: print( "Your activation is {}, but YOLO Layer ID {} convalution havn't activate {}" .format(activation, conv_id, activation)) prev_filters = filters out_filters.append(prev_filters) prev_stride = stride * prev_stride out_strides.append(prev_stride) models.append(model) elif block['type'] == 'maxpool': # maxpool pool_size = int(block['size']) stride = int(block['stride']) if stride == 1 and pool_size % 2: # stride为1,3,5,... # You can use Maxpooldark instead, here is convenient to convert onnx. # Example: [maxpool] size=3 stride=1 model = nn.MaxPool2d(kernel_size=pool_size, stride=stride, padding=pool_size // 2) elif stride == pool_size: # You can use Maxpooldark instead, here is convenient to convert onnx. # Example: [maxpool] size=2 stride=2 model = nn.MaxPool2d(kernel_size=pool_size, stride=stride, padding=0) else: model = MaxPoolDark(pool_size, stride) out_filters.append(prev_filters) prev_stride = stride * prev_stride out_strides.append(prev_stride) models.append(model) elif block['type'] == 'avgpool': model = GlobalAvgPool2d() out_filters.append(prev_filters) models.append(model) elif block['type'] == 'softmax': model = nn.Softmax() out_strides.append(prev_stride) out_filters.append(prev_filters) models.append(model) elif block['type'] == 'cost': if block['_type'] == 'sse': model = nn.MSELoss(reduction='mean') elif block['_type'] == 'L1': model = nn.L1Loss(reduction='mean') elif block['_type'] == 'smooth': model = nn.SmoothL1Loss(reduction='mean') out_filters.append(1) out_strides.append(prev_stride) models.append(model) elif block['type'] == 'reorg': stride = int(block['stride']) prev_filters = stride * stride * prev_filters out_filters.append(prev_filters) prev_stride = prev_stride * stride out_strides.append(prev_stride) models.append(Reorg(stride)) elif block['type'] == 'upsample': stride = int(block['stride']) out_filters.append(prev_filters) prev_stride = prev_stride // stride out_strides.append(prev_stride) models.append(Upsample_expand(stride)) # 上采样 方式1 # models.append(Upsample_interpolate(stride)) # 上采样 方式2 elif block['type'] == 'route': layers = block['layers'].split(',') # -1, -7 ind = len(models) layers = [ int(i) if int(i) > 0 else int(i) + ind for i in layers ] # 通过layers定位到整个网络的下标 if len(layers) == 1: # 一条路径 if 'groups' not in block.keys() or int( block['groups']) == 1: prev_filters = out_filters[layers[0]] prev_stride = out_strides[layers[0]] else: prev_filters = out_filters[layers[0]] // int( block['groups']) prev_stride = out_strides[layers[0]] // int( block['groups']) elif len(layers) == 2: # 两条路径 assert (layers[0] == ind - 1 or layers[1] == ind - 1) prev_filters = out_filters[layers[0]] + out_filters[ layers[1]] prev_stride = out_strides[layers[0]] elif len(layers) == 4: # 四条路径 assert (layers[0] == ind - 1) prev_filters = out_filters[layers[0]] + out_filters[layers[1]] + out_filters[layers[2]] + \ out_filters[layers[3]] prev_stride = out_strides[layers[0]] else: print("route error!!!") out_filters.append(prev_filters) out_strides.append(prev_stride) models.append(EmptyModule()) elif block['type'] == 'shortcut': ind = len(models) prev_filters = out_filters[ind - 1] out_filters.append(prev_filters) prev_stride = out_strides[ind - 1] out_strides.append(prev_stride) models.append(EmptyModule()) elif block['type'] == 'connected': filters = int(block['output']) if block['activation'] == 'linear': model = nn.Linear(prev_filters, filters) elif block['activation'] == 'leaky': model = nn.Sequential(nn.Linear(prev_filters, filters), nn.LeakyReLU(0.1, inplace=True)) elif block['activation'] == 'relu': model = nn.Sequential(nn.Linear(prev_filters, filters), nn.ReLU(inplace=True)) prev_filters = filters out_filters.append(prev_filters) out_strides.append(prev_stride) models.append(model) elif block['type'] == 'region': loss = RegionLoss() anchors = block['anchors'].split(',') loss.anchors = [float(i) for i in anchors] loss.num_classes = int(block['classes']) loss.num_anchors = int(block['num']) loss.anchor_step = len(loss.anchors) // loss.num_anchors loss.object_scale = float(block['object_scale']) loss.noobject_scale = float(block['noobject_scale']) loss.class_scale = float(block['class_scale']) loss.coord_scale = float(block['coord_scale']) out_filters.append(prev_filters) out_strides.append(prev_stride) models.append(loss) elif block['type'] == 'yolo': yolo_layer = YoloLayer() anchors = block['anchors'].split(',') # all anchors anchor_mask = block['mask'].split(',') # anchor mask yolo_layer.anchor_mask = [ int(i) for i in anchor_mask ] # 当前yolo layer的 anchor mask eg.[0,1,2] yolo_layer.anchors = [float(i) for i in anchors ] # 当前yolo layer的 anchors eg.[xx,xx,xx] yolo_layer.num_classes = int( block['classes']) # 当前yolo layer的 classes类别数 eg.80 self.num_classes = yolo_layer.num_classes # DarkNet 类别数 eg.80 yolo_layer.num_anchors = int( block['num']) # 当前yolo layer的 所有的anchors数量 eg.9 yolo_layer.anchor_step = len( yolo_layer.anchors ) // yolo_layer.num_anchors # 索引 anchor的步长 eg.18/9=2 yolo_layer.stride = prev_stride # 此yolo layer特征图相对于原图的步长 yolo_layer.scale_x_y = float(block['scale_x_y']) # xy比例 out_filters.append(prev_filters) out_strides.append(prev_stride) models.append(yolo_layer) else: print('unknown type %s' % (block['type'])) return models
def create_network(self, blocks): """ nn.ModuleList仅仅类似于pytho中的list类型,只是将一系列层装入列表,并没有实现forward()方法,因此也不会有网络模型产生的副作用, 但它有和纯python中的list不同,用nn.ModuleList或者ParameterList包裹模型各个层之后,我们不光可以像python里的list一样对模型的各个层进行索引, 同时这些层的参数将会被自动注册,这些层的参数只有被正确注册之后,优化器才能发现和训练这些参数 这个操作只会生成一个空的list """ models = nn.ModuleList() prev_filters = 3 out_filters = [] prev_stride = 1 out_strides = [] conv_id = 0 for block in blocks: # 遍历 blocks 的时候,模型不断累加到一起 if block['type'] == 'net': #网络参数 prev_filters = int(block['channels']) #第一次的卷积核个数就是看看有多少个通道 continue # 一共就一个net参数表 elif block['type'] == 'convolutional': #卷积层 conv_id = conv_id + 1 # 数据经过多层神经网络后,数据分布发生变化,导致各层参数需要不到调整适应分布变化,这会让收敛速度变慢, # 超参数设定也变得比较复杂,这在论文里作者称作Internal Covariate Shift # batch_normalize 用于防止梯度消失,就是将后面的数据分布进行规整, batch_normalize = int(block['batch_normalize']) # always 1, 除了最后的输出层,每一层都是用了 batch_normalize filters = int(block['filters']) # 卷积核,其实就是滤波器。在每次迭代中会进行更新参数 kernel_size = int(block['size']) stride = int(block['stride']) # 步长 is_pad = int(block['pad']) # padding 过程 这里的padding 始终=1,仅用于表示:需要 padding pad = (kernel_size - 1) // 2 if is_pad else 0 # padding 大小 activation = block['activation'] # 激活层,激活函数是用来加入非线性因素的,因为线性模型的表达能力不够。 model = nn.Sequential() # 模型为空,通过add_module添加模型结构 if batch_normalize: # add_module(self, name, module) # nn.Conv2d(self, in_channels, out_channels, kernel_size, stride=1, # padding=0, dilation=1, groups=1, # bias=True, padding_mode='zeros') model.add_module('conv{0}'.format(conv_id), nn.Conv2d(prev_filters, filters, kernel_size, stride, pad, bias=False)) # print('create_network: conv{0}'.format(conv_id)) # 块标准化的目的就是让传输的数据合理的分布,加速训练的过程 model.add_module('bn{0}'.format(conv_id), nn.BatchNorm2d(filters)) # model.add_module('bn{0}'.format(conv_id), BN2d(filters)) else: model.add_module('conv{0}'.format(conv_id), nn.Conv2d(prev_filters, filters, kernel_size, stride, pad)) if activation == 'leaky': model.add_module('leaky{0}'.format(conv_id), nn.LeakyReLU(0.1, inplace=True)) elif activation == 'relu': model.add_module('relu{0}'.format(conv_id), nn.ReLU(inplace=True)) elif activation == 'mish': model.add_module('mish{0}'.format(conv_id), Mish()) else: print(conv_id,"convalution havn't activate {}".format(activation)) prev_filters = filters out_filters.append(prev_filters) prev_stride = stride * prev_stride out_strides.append(prev_stride) models.append(model) elif block['type'] == 'maxpool': pool_size = int(block['size']) stride = int(block['stride']) if stride == 1 and pool_size % 2: # You can use Maxpooldark instead, here is convenient to convert onnx. # Example: [maxpool] size=3 stride=1 model = nn.MaxPool2d(kernel_size=pool_size, stride=stride, padding=pool_size // 2) elif stride == pool_size: # You can use Maxpooldark instead, here is convenient to convert onnx. # Example: [maxpool] size=2 stride=2 model = nn.MaxPool2d(kernel_size=pool_size, stride=stride, padding=0) else: model = MaxPoolDark(pool_size, stride) out_filters.append(prev_filters) prev_stride = stride * prev_stride out_strides.append(prev_stride) models.append(model) elif block['type'] == 'avgpool': model = GlobalAvgPool2d() out_filters.append(prev_filters) models.append(model) elif block['type'] == 'softmax': model = nn.Softmax() out_strides.append(prev_stride) out_filters.append(prev_filters) models.append(model) elif block['type'] == 'cost': if block['_type'] == 'sse': model = nn.MSELoss(reduction='mean') elif block['_type'] == 'L1': model = nn.L1Loss(reduction='mean') elif block['_type'] == 'smooth': model = nn.SmoothL1Loss(reduction='mean') out_filters.append(1) out_strides.append(prev_stride) models.append(model) elif block['type'] == 'reorg': stride = int(block['stride']) prev_filters = stride * stride * prev_filters out_filters.append(prev_filters) prev_stride = prev_stride * stride out_strides.append(prev_stride) models.append(Reorg(stride)) elif block['type'] == 'upsample': stride = int(block['stride']) out_filters.append(prev_filters) prev_stride = prev_stride // stride out_strides.append(prev_stride) models.append(Upsample_expand(stride)) # models.append(Upsample_interpolate(stride)) elif block['type'] == 'route': layers = block['layers'].split(',') ind = len(models) layers = [int(i) if int(i) > 0 else int(i) + ind for i in layers] if len(layers) == 1: if 'groups' not in block.keys() or int(block['groups']) == 1: prev_filters = out_filters[layers[0]] prev_stride = out_strides[layers[0]] else: prev_filters = out_filters[layers[0]] // int(block['groups']) prev_stride = out_strides[layers[0]] // int(block['groups']) elif len(layers) == 2: assert (layers[0] == ind - 1 or layers[1] == ind - 1) prev_filters = out_filters[layers[0]] + out_filters[layers[1]] prev_stride = out_strides[layers[0]] elif len(layers) == 4: assert (layers[0] == ind - 1) prev_filters = out_filters[layers[0]] + out_filters[layers[1]] + out_filters[layers[2]] + \ out_filters[layers[3]] prev_stride = out_strides[layers[0]] else: print("route error!!!") out_filters.append(prev_filters) out_strides.append(prev_stride) models.append(EmptyModule()) elif block['type'] == 'shortcut': ind = len(models) prev_filters = out_filters[ind - 1] out_filters.append(prev_filters) prev_stride = out_strides[ind - 1] out_strides.append(prev_stride) models.append(EmptyModule()) elif block['type'] == 'connected': filters = int(block['output']) if block['activation'] == 'linear': model = nn.Linear(prev_filters, filters) elif block['activation'] == 'leaky': model = nn.Sequential( nn.Linear(prev_filters, filters), nn.LeakyReLU(0.1, inplace=True)) elif block['activation'] == 'relu': model = nn.Sequential( nn.Linear(prev_filters, filters), nn.ReLU(inplace=True)) prev_filters = filters out_filters.append(prev_filters) out_strides.append(prev_stride) models.append(model) elif block['type'] == 'region': loss = RegionLoss() anchors = block['anchors'].split(',') loss.anchors = [float(i) for i in anchors] loss.num_classes = int(block['classes']) loss.num_anchors = int(block['num']) loss.anchor_step = len(loss.anchors) // loss.num_anchors loss.object_scale = float(block['object_scale']) loss.noobject_scale = float(block['noobject_scale']) loss.class_scale = float(block['class_scale']) loss.coord_scale = float(block['coord_scale']) out_filters.append(prev_filters) out_strides.append(prev_stride) models.append(loss) elif block['type'] == 'yolo': yolo_layer = YoloLayer() anchors = block['anchors'].split(',') anchor_mask = block['mask'].split(',') yolo_layer.anchor_mask = [int(i) for i in anchor_mask] yolo_layer.anchors = [float(i) for i in anchors] yolo_layer.num_classes = int(block['classes']) self.num_classes = yolo_layer.num_classes yolo_layer.num_anchors = int(block['num']) yolo_layer.anchor_step = len(yolo_layer.anchors) // yolo_layer.num_anchors yolo_layer.stride = prev_stride yolo_layer.scale_x_y = float(block['scale_x_y']) # yolo_layer.object_scale = float(block['object_scale']) # yolo_layer.noobject_scale = float(block['noobject_scale']) # yolo_layer.class_scale = float(block['class_scale']) # yolo_layer.coord_scale = float(block['coord_scale']) out_filters.append(prev_filters) out_strides.append(prev_stride) models.append(yolo_layer) else: print('unknown type %s' % (block['type'])) return models