def generate(self): self.score = 0.01 self.iou = 0.5 model_path = os.path.expanduser(self.model_path) assert model_path.endswith( '.h5'), 'Keras model or weights must be a .h5 file.' #---------------------------------------------------# # 计算先验框的数量和种类的数量 #---------------------------------------------------# num_anchors = len(self.anchors) num_classes = len(self.class_names) #---------------------------------------------------------# # 载入模型,如果原来的模型里已经包括了模型结构则直接载入。 # 否则先构建模型再载入 #---------------------------------------------------------# try: self.yolo_model = load_model(model_path, compile=False) except: self.yolo_model = yolo_body(Input(shape=(None, None, 3)), num_anchors // 3, num_classes, self.backbone, self.alpha) self.yolo_model.load_weights(self.model_path) else: assert self.yolo_model.layers[-1].output_shape[-1] == \ num_anchors/len(self.yolo_model.output) * (num_classes + 5), \ 'Mismatch between model and given anchor and class sizes' print('{} model, anchors, and classes loaded.'.format(model_path)) # 画框设置不同的颜色 hsv_tuples = [(x / len(self.class_names), 1., 1.) for x in range(len(self.class_names))] self.colors = list(map(lambda x: colorsys.hsv_to_rgb(*x), hsv_tuples)) self.colors = list( map(lambda x: (int(x[0] * 255), int(x[1] * 255), int(x[2] * 255)), self.colors)) # 打乱颜色 np.random.seed(10101) np.random.shuffle(self.colors) np.random.seed(None) self.input_image_shape = K.placeholder(shape=(2, )) #---------------------------------------------------------# # 在yolo_eval函数中,我们会对预测结果进行后处理 # 后处理的内容包括,解码、非极大抑制、门限筛选等 #---------------------------------------------------------# boxes, scores, classes = yolo_eval( self.yolo_model.output, self.anchors, num_classes, self.input_image_shape, max_boxes=self.max_boxes, score_threshold=self.score, iou_threshold=self.iou, letterbox_image=self.letterbox_image) return boxes, scores, classes
def generate(self): model_path = os.path.expanduser(self.model_path) assert model_path.endswith( '.h5'), 'Keras model or weights must be a .h5 file.' # 计算anchor数量 num_anchors = len(self.anchors) num_classes = len(self.class_names) # 载入模型,如果原来的模型里已经包括了模型结构则直接载入。 # 否则先构建模型再载入 self.yolo_model = yolo_body(Input(shape=(None, None, 3)), num_anchors // 3, num_classes) self.yolo_model.load_weights(self.model_path) print('{} model, anchors, and classes loaded.'.format(model_path)) # 画框设置不同的颜色 hsv_tuples = [(x / len(self.class_names), 1., 1.) for x in range(len(self.class_names))] self.colors = list(map(lambda x: colorsys.hsv_to_rgb(*x), hsv_tuples)) self.colors = list( map(lambda x: (int(x[0] * 255), int(x[1] * 255), int(x[2] * 255)), self.colors)) # 打乱颜色 np.random.seed(10101) np.random.shuffle(self.colors) np.random.seed(None) if self.eager: self.input_image_shape = Input([ 2, ], batch_size=1) inputs = [*self.yolo_model.output, self.input_image_shape] outputs = Lambda(yolo_eval, output_shape=(1, ), name='yolo_eval', arguments={ 'anchors': self.anchors, 'num_classes': len(self.class_names), 'image_shape': self.model_image_size, 'score_threshold': self.score, 'eager': True, 'max_boxes': self.max_boxes })(inputs) self.yolo_model = Model( [self.yolo_model.input, self.input_image_shape], outputs) else: self.input_image_shape = K.placeholder(shape=(2, )) self.boxes, self.scores, self.classes = yolo_eval( self.yolo_model.output, self.anchors, num_classes, self.input_image_shape, max_boxes=self.max_boxes, score_threshold=self.score, iou_threshold=self.iou)
def generate(self): model_path = os.path.expanduser(self.model_path) assert model_path.endswith( '.h5'), 'Keras model or weights must be a .h5 file.' # 计算anchor数量 num_anchors = len(self.anchors) num_classes = len(self.class_names) # 载入模型,如果原来的模型里已经包括了模型结构则直接载入。 # 否则先构建模型再载入 try: self.yolo_model = load_model(model_path, compile=False) except: self.yolo_model = yolo_body(Input(shape=(None, None, 3)), num_anchors // 3, num_classes) self.yolo_model.load_weights(self.model_path) else: assert self.yolo_model.layers[-1].output_shape[-1] == \ num_anchors/len(self.yolo_model.output) * (num_classes + 5), \ 'Mismatch between model and given anchor and class sizes' print('{} model, anchors, and classes loaded.'.format(model_path)) # 画框设置不同的颜色 #参数前带个*表示元组, #里是因为colorsys.hsv_to_rgb函数所需传入对象必须是元组,map函数则要求hsv_tuples为可迭代对象 hsv_tuples = [(x / len(self.class_names), 1., 1.) for x in range(len(self.class_names))] self.colors = list( map(lambda x: colorsys.hsv_to_rgb(*x), hsv_tuples)) # 将存有hsv颜色空间的颜色元组列表,转换成rgb颜色空间的颜色元组列表 self.colors = list( map(lambda x: (int(x[0] * 255), int(x[1] * 255), int(x[2] * 255)), self.colors)) # 打乱颜色 np.random.seed(10101) np.random.shuffle(self.colors) np.random.seed(None) self.input_image_shape = K.placeholder( shape=(2, )) # shape=(2, ) 表示行数是两行,列不定 boxes, scores, classes = yolo_eval( self.yolo_model.output, self.anchors, # 返回框的位置,得分,种类 num_classes, self.input_image_shape, score_threshold=self.score, iou_threshold=self.iou) return boxes, scores, classes
def generate(self): model_path = os.path.expanduser(self.model_path) assert model_path.endswith('.h5'), 'Keras model or weights must be a .h5 file.' #---------------------------------------------------# # 计算先验框的数量和种类的数量 #---------------------------------------------------# num_anchors = len(self.anchors) num_classes = len(self.class_names) #---------------------------------------------------------# # 载入模型 #---------------------------------------------------------# self.yolo_model = yolo_body(Input(shape=(None,None,3)), num_anchors//3, num_classes, self.backbone, self.alpha) self.yolo_model.load_weights(self.model_path) print('{} model, anchors, and classes loaded.'.format(model_path)) # 画框设置不同的颜色 hsv_tuples = [(x / len(self.class_names), 1., 1.) for x in range(len(self.class_names))] self.colors = list(map(lambda x: colorsys.hsv_to_rgb(*x), hsv_tuples)) self.colors = list( map(lambda x: (int(x[0] * 255), int(x[1] * 255), int(x[2] * 255)), self.colors)) # 打乱颜色 np.random.seed(10101) np.random.shuffle(self.colors) np.random.seed(None) #---------------------------------------------------------# # 在yolo_eval函数中,我们会对预测结果进行后处理 # 后处理的内容包括,解码、非极大抑制、门限筛选等 #---------------------------------------------------------# if self.eager: self.input_image_shape = Input([2,],batch_size=1) inputs = [*self.yolo_model.output, self.input_image_shape] outputs = Lambda(yolo_eval, output_shape=(1,), name='yolo_eval', arguments={'anchors': self.anchors, 'num_classes': len(self.class_names), 'image_shape': self.model_image_size, 'score_threshold': self.score, 'eager': True, 'max_boxes': self.max_boxes, 'letterbox_image': self.letterbox_image})(inputs) self.yolo_model = Model([self.yolo_model.input, self.input_image_shape], outputs) else: self.input_image_shape = K.placeholder(shape=(2, )) self.boxes, self.scores, self.classes = yolo_eval(self.yolo_model.output, self.anchors, num_classes, self.input_image_shape, max_boxes=self.max_boxes, score_threshold=self.score, iou_threshold=self.iou, letterbox_image = self.letterbox_image)
def generate(self): score = CONFIG.DETECT.SCORE iou = CONFIG.DETECT.IOU model_path = os.path.expanduser(self.model_path) assert model_path.endswith( '.h5'), 'Keras model or weights must be a .h5 file.' num_anchors = len(self.anchors) num_classes = len(self.class_names) try: self.yolo_model = load_model(model_path, compile=False) except: self.yolo_model = yolo_body(Input(shape=(None, None, 3)), num_anchors // 3, num_classes) self.yolo_model.load_weights(self.model_path) else: assert self.yolo_model.layers[-1].output_shape[-1] == \ num_anchors / len(self.yolo_model.output) * (num_classes + 5), \ 'Mismatch between model and given anchor and class sizes' print('{} model, anchors, and classes loaded.'.format(model_path)) # draw bounding boxes hsv_tuples = [(x / len(self.class_names), 1., 1.) for x in range(len(self.class_names))] self.colors = list(map(lambda x: colorsys.hsv_to_rgb(*x), hsv_tuples)) self.colors = list( map(lambda x: (int(x[0] * 255), int(x[1] * 255), int(x[2] * 255)), self.colors)) # random color np.random.seed(10101) np.random.shuffle(self.colors) np.random.seed(None) self.input_image_shape = K.placeholder(shape=(2, )) boxes, scores, classes = yolo_eval(self.yolo_model.output, self.anchors, num_classes, self.input_image_shape, score_threshold=score, iou_threshold=iou, nms_method=self.nms_method, diou_threshold=self.diou_threshold) return boxes, scores, classes
def generate(self): model_path = os.path.expanduser(self.model_path) assert model_path.endswith( '.h5'), 'Keras model or weights must be a .h5 file.' ''' self.yolo_model = load_model(model_path, custom_objects={'Mish': Mish}, compile=False) print('{} model, anchors, and classes loaded.'.format(model_path)) ''' num_anchors = len(self.anchors) num_classes = len(self.class_names) try: self.yolo_model = load_model(model_path, compile=False) except: self.yolo_model = yolo_body(Input(shape=(None, None, 3)), num_anchors // 3, num_classes) self.yolo_model.load_weights(self.model_path) else: assert self.yolo_model.layers[-1].output_shape[-1] == \ num_anchors/len(self.yolo_model.output) * (num_classes + 5), \ 'Mismatch between model and given anchor and class sizes' print('{} model, anchors, and classes loaded.'.format(model_path)) # Generate colors for drawing bounding boxes. hsv_tuples = [(x / len(self.class_names), 1., 1.) for x in range(len(self.class_names))] self.colors = list(map(lambda x: colorsys.hsv_to_rgb(*x), hsv_tuples)) self.colors = list( map(lambda x: (int(x[0] * 255), int(x[1] * 255), int(x[2] * 255)), self.colors)) np.random.seed(10101) # Fixed seed for consistent colors across runs. np.random.shuffle( self.colors) # Shuffle colors to decorrelate adjacent classes. np.random.seed(None) # Reset seed to default. # Generate output tensor targets for filtered bounding boxes. self.input_image_shape = K.placeholder(shape=(2, )) if self.gpu_num >= 2: self.yolo_model = multi_gpu_model(self.yolo_model, gpus=self.gpu_num) boxes, scores, classes = yolo_eval(self.yolo_model.output, self.anchors, len(self.class_names), self.input_image_shape, score_threshold=self.score, iou_threshold=self.iou) return boxes, scores, classes
def generate(self): model_path = os.path.expanduser(self.model_path) assert model_path.endswith('.h5'), 'Keras model or weights must be a .h5 file.' #---------------------------------------------------# # 计算先验框的数量和种类的数量 #---------------------------------------------------# num_anchors = len(self.anchors) num_classes = len(self.class_names) #---------------------------------------------------------# # 载入模型,如果原来的模型里已经包括了模型结构则直接载入。 # 否则先构建模型再载入 #---------------------------------------------------------# try: print("load model") self.yolo_model = load_model(model_path, compile=False) except: print("build model") self.yolo_model = yolo_body(Input(shape=(self.model_image_size[0],self.model_image_size[1],3)), num_anchors//3, num_classes) self.yolo_model.load_weights(self.model_path) else: assert self.yolo_model.layers[-1].output_shape[-1] == \ num_anchors/len(self.yolo_model.output) * (num_classes + 5), \ 'Mismatch between model and given anchor and class sizes' print('{} model, anchors, and classes loaded.'.format(model_path)) self.yolo_model.summary() # 画框设置不同的颜色 hsv_tuples = [(x / len(self.class_names), 1., 1.) for x in range(len(self.class_names))] self.colors = list(map(lambda x: colorsys.hsv_to_rgb(*x), hsv_tuples)) self.colors = list( map(lambda x: (int(x[0] * 255), int(x[1] * 255), int(x[2] * 255)), self.colors)) # 打乱颜色 np.random.seed(10101) np.random.shuffle(self.colors) np.random.seed(None) return
def generate(self): model_path = os.path.expanduser(self.model_path) assert model_path.endswith('.h5'), 'Keras model or weights must be a .h5 file.' # Calculate the number of Anchor num_anchors = len(self.anchors) num_classes = len(self.class_names) # Load the model directly if the original model already contains the model structure. # Otherwise, build the model first and load it later try: self.yolo_model = load_model(model_path, compile=False) except: self.yolo_model = yolo_body(Input(shape=(None, None, 3)), num_anchors // 3, num_classes) self.yolo_model.load_weights(self.model_path) else: assert self.yolo_model.layers[-1].output_shape[-1] == \ num_anchors / len(self.yolo_model.output) * (num_classes + 5), \ 'Mismatch between model and given anchor and class sizes' print('{} model, anchors, and classes loaded.'.format(model_path)) # The frame is set in different colors hsv_tuples = [(x / len(self.class_names), 1., 1.) for x in range(len(self.class_names))] self.colors = list(map(lambda x: colorsys.hsv_to_rgb(*x), hsv_tuples)) self.colors = list( map(lambda x: (int(x[0] * 255), int(x[1] * 255), int(x[2] * 255)), self.colors)) # Disturb the color np.random.seed(10101) np.random.shuffle(self.colors) np.random.seed(None) self.input_image_shape = K.placeholder(shape=(2,)) boxes, scores, classes = yolo_eval(self.yolo_model.output, self.anchors, num_classes, self.input_image_shape, score_threshold=self.score, iou_threshold=self.iou) return boxes, scores, classes
def generate(self): num_anchors = len(self.anchors) num_classes = len(self.class_names) try: self.yolo_model = load_model(self.model_path, compile=False) except Exception: self.yolo_model = yolo_body(Input(shape=(None, None, 3)), num_anchors // 3, num_classes) self.yolo_model.load_weights(self.model_path) else: assert self.yolo_model.layers[-1].output_shape[-1] == num_anchors / len(self.yolo_model.output) * (num_classes + 5), \ 'Mismatch between model and given anchor and class sizes' print('{} model, anchors, and classes loaded.'.format(self.model_path)) boxes, scores, classes = yolo_eval(self.yolo_model.output, self.anchors, num_classes, self.input_image_shape, score_threshold=self.score, iou_threshold=self.iou) return boxes, scores, classes
#--------------------------------------------# # 该部分代码只用于看网络结构,并非测试代码 # map测试请看get_dr_txt.py、get_gt_txt.py # 和get_map.py #--------------------------------------------# from tensorflow.keras.layers import Input from nets.yolo4 import yolo_body if __name__ == "__main__": inputs = Input([416, 416, 3]) model = yolo_body(inputs, 3, 80) model.summary() for i, layer in enumerate(model.layers): print(i, layer.name)
label_smoothing = 0 regularization = True #-------------------------------# # Dataloder的使用 #-------------------------------# Use_Data_Loader = True #------------------------------------------------------# # 创建yolo模型 #------------------------------------------------------# image_input = Input(shape=(None, None, 3)) h, w = input_shape print('Create YOLOv4 model with {} anchors and {} classes.'.format( num_anchors, num_classes)) model_body = yolo_body(image_input, num_anchors // 3, num_classes, backbone, alpha) #------------------------------------------------------# # 载入预训练权重 #------------------------------------------------------# print('Load weights {}.'.format(weights_path)) model_body.load_weights(weights_path, by_name=True, skip_mismatch=True) #-------------------------------------------------------------------------------# # 训练参数的设置 # logging表示tensorboard的保存地址 # checkpoint用于设置权值保存的细节,period用于修改多少epoch保存一次 # reduce_lr用于设置学习率下降的方式 # early_stopping用于设定早停,val_loss多次不下降自动结束训练,表示模型基本收敛 #-------------------------------------------------------------------------------# val_split = 0.1
anchors_wh_26 = np.array(anchors[3:6]) anchors_wh_26 = np.tile(np.reshape(anchors_wh_26, (1, 1, 3, 2)), reps=(26, 26, 1, 1)) anchors_wh_26 = tf.constant(anchors_wh_26, dtype=tf.float32) anchor_wh.append(anchors_wh_26) anchors_wh_52 = np.array(anchors[:3]) anchors_wh_52 = np.tile(np.reshape(anchors_wh_52, (1, 1, 3, 2)), reps=(52, 52, 1, 1)) anchors_wh_52 = tf.constant(anchors_wh_52, dtype=tf.float32) anchor_wh.append(anchors_wh_52) inputs_keras = keras.Input(shape=(416, 416, 3)) yolo4 = yolo_body(inputs=inputs_keras, num_anchors=num_anchors, num_classes=num_classes) yolo4.load_weights(weight_path) def save_model(inputs, image_shape, input_shape, num_anchors, num_classes, score_thres, iou_thres, scales_xy=None): """package model with forward propagation and post processing
def main(): # 标签的位置 annotation_path = '2020_train_all.txt' # 获取classes和anchor的位置 classes_path = 'model_data/our_classes.txt' anchors_path = 'model_data/yolo4_anchors.txt' #------------------------------------------------------# # 权值文件请看README,百度网盘下载 # 训练自己的数据集时提示维度不匹配正常 # 预测的东西都不一样了自然维度不匹配 #------------------------------------------------------# weights_path = 'model_data/last9.h5' # 获得classes和anchor class_names = get_classes(classes_path) anchors = get_anchors(anchors_path) # 一共有多少类 num_classes = len(class_names) num_anchors = len(anchors) # 训练后的模型保存的位置 log_dir = 'logs/' # 输入的shape大小 # 显存比较小可以使用416x416 # 现存比较大可以使用608x608 input_shape = (608, 608) mosaic = True Cosine_scheduler = False label_smoothing = 0 # 清除session K.clear_session() # 输入的图像为 image_input = Input(shape=(None, None, 3)) h, w = input_shape # 创建yolo模型 print('Create YOLOv4 model with {} anchors and {} classes.'.format( num_anchors, num_classes)) model_body = yolo_body(image_input, num_anchors // 3, num_classes) # 载入预训练权重 print('Load weights {}.'.format(weights_path)) model_body.load_weights(weights_path, by_name=True, skip_mismatch=True) # y_true为13,13,3,85 # 26,26,3,85 # 52,52,3,85 y_true = [Input(shape=(h//{0:32, 1:16, 2:8}[l], w//{0:32, 1:16, 2:8}[l], \ num_anchors//3, num_classes+5)) for l in range(3)] # 输入为*model_body.input, *y_true # 输出为model_loss loss_input = [*model_body.output, *y_true] model_loss = Lambda(yolo_loss, output_shape=(1, ), name='yolo_loss', arguments={ 'anchors': anchors, 'num_classes': num_classes, 'ignore_thresh': 0.5, 'label_smoothing': label_smoothing })(loss_input) model = Model([model_body.input, *y_true], model_loss) # 训练参数设置 logging = TensorBoard(log_dir=log_dir) checkpoint = ModelCheckpoint( log_dir + 'ep{epoch:03d}-loss{loss:.3f}-val_loss{val_loss:.3f}.h5', monitor='val_loss', save_weights_only=True, save_best_only=False, period=1) early_stopping = EarlyStopping(monitor='val_loss', min_delta=0, patience=6, verbose=1) # 0.1用于验证,0.9用于训练 val_split = 0.1 with open(annotation_path) as f: lines = f.readlines() np.random.seed(10101) np.random.shuffle(lines) np.random.seed(None) num_val = int(len(lines) * val_split) num_train = len(lines) - num_val #------------------------------------------------------# # 主干特征提取网络特征通用,冻结训练可以加快训练速度 # 也可以在训练初期防止权值被破坏。 # Init_Epoch为起始世代 # Freeze_Epoch为冻结训练的世代 # Epoch总训练世代 # 提示OOM或者显存不足请调小Batch_size #------------------------------------------------------# freeze_layers = 249 for i in range(freeze_layers): model_body.layers[i].trainable = False print('Freeze the first {} layers of total {} layers.'.format( freeze_layers, len(model_body.layers))) # 调整非主干模型first if True: Init_epoch = 0 Freeze_epoch = 50 # batch_size大小,每次喂入多少数据 batch_size = 8 # 最大学习率 learning_rate_base = 1e-3 if Cosine_scheduler: # 预热期 warmup_epoch = int((Freeze_epoch - Init_epoch) * 0.2) # 总共的步长 total_steps = int( (Freeze_epoch - Init_epoch) * num_train / batch_size) # 预热步长 warmup_steps = int(warmup_epoch * num_train / batch_size) # 学习率 reduce_lr = WarmUpCosineDecayScheduler( learning_rate_base=learning_rate_base, total_steps=total_steps, warmup_learning_rate=1e-4, warmup_steps=warmup_steps, hold_base_rate_steps=num_train, min_learn_rate=1e-6) model.compile(optimizer=Adam(), loss={ 'yolo_loss': lambda y_true, y_pred: y_pred }) else: reduce_lr = ReduceLROnPlateau(monitor='val_loss', factor=0.5, patience=2, verbose=1) model.compile(optimizer=Adam(learning_rate_base), loss={ 'yolo_loss': lambda y_true, y_pred: y_pred }) print('Train on {} samples, val on {} samples, with batch size {}.'. format(num_train, num_val, batch_size)) model.fit_generator( data_generator(lines[:num_train], batch_size, input_shape, anchors, num_classes, mosaic=mosaic), steps_per_epoch=max(1, num_train // batch_size), validation_data=data_generator(lines[num_train:], batch_size, input_shape, anchors, num_classes, mosaic=False), validation_steps=max(1, num_val // batch_size), epochs=Freeze_epoch, initial_epoch=Init_epoch, callbacks=[logging, checkpoint, reduce_lr, early_stopping]) model.save_weights(log_dir + 'trained_weights_stage_1.h5') for i in range(freeze_layers): model_body.layers[i].trainable = True # 解冻后训练 if True: Freeze_epoch = 50 Epoch = 100 # batch_size大小,每次喂入多少数据 batch_size = 2 # 最大学习率 learning_rate_base = 1e-4 if Cosine_scheduler: # 预热期 warmup_epoch = int((Epoch - Freeze_epoch) * 0.2) # 总共的步长 total_steps = int((Epoch - Freeze_epoch) * num_train / batch_size) # 预热步长 warmup_steps = int(warmup_epoch * num_train / batch_size) # 学习率 reduce_lr = WarmUpCosineDecayScheduler( learning_rate_base=learning_rate_base, total_steps=total_steps, warmup_learning_rate=1e-5, warmup_steps=warmup_steps, hold_base_rate_steps=num_train // 2, min_learn_rate=1e-6) model.compile(optimizer=Adam(), loss={ 'yolo_loss': lambda y_true, y_pred: y_pred }) else: reduce_lr = ReduceLROnPlateau(monitor='val_loss', factor=0.5, patience=2, verbose=1) model.compile(optimizer=Adam(learning_rate_base), loss={ 'yolo_loss': lambda y_true, y_pred: y_pred }) print('Train on {} samples, val on {} samples, with batch size {}.'. format(num_train, num_val, batch_size)) model.fit_generator( data_generator(lines[:num_train], batch_size, input_shape, anchors, num_classes, mosaic=mosaic), steps_per_epoch=max(1, num_train // batch_size), validation_data=data_generator(lines[num_train:], batch_size, input_shape, anchors, num_classes, mosaic=False), validation_steps=max(1, num_val // batch_size), epochs=Epoch, initial_epoch=Freeze_epoch, callbacks=[logging, checkpoint, reduce_lr, early_stopping]) model.save_weights(log_dir + 'last1.h5')
def trainModel(self, mosaic=True, cosine_scheduler=True, label_smoothing=0.1): """ """ anchors = get_anchors(self.anchors_path) num_classes = len(self.classes) num_anchors = len(anchors) K.clear_session() image_input = Input(shape=(None, None, 3)) h, w = self.input_shape print('Create YOLOv4 model with {} anchors and {} classes.'.format(num_anchors, num_classes)) # model_body = Model(image_input, [P5_output, P4_output, P3_output]) model_body = yolo_body(image_input, num_anchors // 3, num_classes) print('Load weights {}.'.format(self.pretrain_model)) model_body.load_weights(self.pretrain_model, by_name=True, skip_mismatch=True) # y_true = [Input(shape=(h//32,w//32,3,cls+5), Input(shape=(h//16,w//16,3,cls+5), Input(shape=(h//8,w//8,3,cls+5)] y_true = [Input(shape=(h // {0: 32, 1: 16, 2: 8}[i], w // {0: 32, 1: 16, 2: 8}[i], num_anchors // 3, num_classes + 5)) for i in range(3)] # model_body.output = [P5_output, P4_output, P3_output] loss_input = [*model_body.output, *y_true] model_loss = Lambda(yolo_loss, output_shape=(1,), name='yolo_loss', arguments={'anchors': anchors, 'num_classes': num_classes, 'ignore_thresh': 0.5, 'label_smoothing': label_smoothing})(loss_input) model = Model([model_body.input, *y_true], model_loss) # plot_model(model, to_file="yolov4_loss_model.png", show_shapes=True, show_layer_names=True) logging = TensorBoard(log_dir=self.log_dir) checkpoint = ModelCheckpoint(self.log_dir + 'epoch{epoch:03d}-loss{loss:.3f}-val_loss{val_loss:.3f}.h5', monitor='val_loss', save_weights_only=True, save_best_only=False, period=1) early_stopping = EarlyStopping(monitor='val_loss', min_delta=0, patience=10, verbose=1) val_split = 0.1 with open(self.annotation_path) as f: lines = f.readlines() np.random.seed(10101) np.random.shuffle(lines) np.random.seed(None) num_val = int(len(lines) * val_split) num_train = len(lines) - num_val # ------------------------------------------------------# # backbone extract general feature in network # freeze some head layers can speed up training, and prevent weights from influence in early epoch # ------------------------------------------------------# freeze_layers = 249 for i in range(freeze_layers): model_body.layers[i].trainable = False print('Freeze the first {} layers of total {} layers.'.format(freeze_layers, len(model_body.layers))) init_epoch = 0 freeze_epoch = self.epochs // 2 batch_size = self.batch_size * 2 learning_rate_base = 1e-3 if cosine_scheduler: warm_up_epoch = int((freeze_epoch - init_epoch) * 0.2) total_steps = int((freeze_epoch - init_epoch) * num_train / batch_size) warm_up_steps = int(warm_up_epoch * num_train / batch_size) reduce_lr = WarmUpCosineDecayScheduler(learning_rate_base=learning_rate_base, total_steps=total_steps, warmup_learning_rate=1e-4, warmup_steps=warm_up_steps, hold_base_rate_steps=num_train, min_learn_rate=1e-6) model.compile(optimizer=Adam(), loss=dummy_loss) else: reduce_lr = ReduceLROnPlateau(monitor='val_loss', factor=0.5, patience=2, verbose=1, min_lr=1e-6) model.compile(optimizer=Adam(learning_rate_base), loss=dummy_loss) print('Train on {} samples, val on {} samples, with batch size {}.'.format(num_train, num_val, batch_size)) model.fit_generator( data_generator(lines[:num_train], batch_size, self.input_shape, anchors, num_classes, mosaic=mosaic), steps_per_epoch=max(1, num_train // batch_size), validation_data=data_generator(lines[num_train:], batch_size, self.input_shape, anchors, num_classes, mosaic=False), validation_steps=max(1, num_val // batch_size), epochs=freeze_epoch, initial_epoch=init_epoch, callbacks=[logging, checkpoint, reduce_lr, early_stopping]) model.save_weights(self.log_dir + 'trained_weights_stage_1.h5') for i in range(freeze_layers): model_body.layers[i].trainable = True print("\n\nStarting Training all Layers....\n\n") batch_size = self.batch_size learning_rate_base = 1e-4 if cosine_scheduler: warm_up_epoch = int((self.epochs - freeze_epoch) * 0.2) total_steps = int((self.epochs - freeze_epoch) * num_train / batch_size) warm_up_steps = int(warm_up_epoch * num_train / batch_size) reduce_lr = WarmUpCosineDecayScheduler(learning_rate_base=learning_rate_base, total_steps=total_steps, warmup_learning_rate=1e-5, warmup_steps=warm_up_steps, hold_base_rate_steps=num_train // 2, min_learn_rate=1e-6) model.compile(optimizer=Adam(), loss=dummy_loss) else: reduce_lr = ReduceLROnPlateau(monitor='val_loss', factor=0.5, patience=2, verbose=1, min_lr=1e-6) model.compile(optimizer=Adam(learning_rate_base), loss=dummy_loss) print('Train on {} samples, val on {} samples, with batch size {}.'.format(num_train, num_val, batch_size)) model.fit_generator( data_generator(lines[:num_train], batch_size, self.input_shape, anchors, num_classes, mosaic=mosaic), steps_per_epoch=max(1, num_train // batch_size), validation_data=data_generator(lines[num_train:], batch_size, self.input_shape, anchors, num_classes, mosaic=False), validation_steps=max(1, num_val // batch_size), epochs=self.epochs, initial_epoch=freeze_epoch, callbacks=[logging, checkpoint, reduce_lr, early_stopping]) model.save_weights(self.log_dir + 'last1.h5')
#--------------------------------------------# # 该部分代码只用于看网络结构,并非测试代码 # map测试请看get_dr_txt.py、get_gt_txt.py # 和get_map.py #--------------------------------------------# from keras.layers import Input from nets.yolo4 import yolo_body if __name__ == "__main__": inputs = Input([416,416,3]) model = yolo_body(inputs, 3, 80, backbone='mobilenetv1', alpha=1) model.summary() # mobilenetv1 41,005,757 # mobilenetv2 39,124,541 # mobilenetv3 40,043,389 # 修改了PANET的mobilenetv1 12,754,109 # 修改了PANET的mobilenetv2 10,872,893 # 修改了PANET的mobilenetv3 11,791,741 # 修改了PANET的mobilenetv1-0.25 680,381 # 修改了PANET的mobilenetv2-0.5 2,370,541 # 修改了PANET的mobilenetv3-0.75 6,315,309 # for i,layer in enumerate(model.layers): # print(i,layer.name)
def build_model(self, training=True): input_width = self.config['model']['input_width'] input_height = self.config['model']['input_height'] input_depth = self.config['model']['input_depth'] class_num = self.config['model']['class_num'] backbone = self.config['model']['backbone'] train_base = self.config['train']['train_base'] weights_path = self.config['train']['pretrained_weights'] num_anchors = len(self.anchors) label_smoothing = 0 normalize = False K.clear_session() #------------------------------------------------------# # 创建yolo模型 #------------------------------------------------------# image_input = Input(shape=(input_width, input_height, 3)) print('Create YOLOv4 model with {} anchors and {} classes.'.format( num_anchors, class_num)) model_body = yolo_body(image_input, num_anchors // 3, class_num) if training is False: return model_body if train_base is False: freeze_layers = 249 for i in range(freeze_layers): model_body.layers[i].trainable = False print('Freeze the first {} layers of total {} layers.'.format( freeze_layers, len(model_body.layers))) # model_body.summary() #------------------------------------------------------# # 载入预训练权重 #------------------------------------------------------# # print('Load weights {}.'.format(weights_path)) # model_body.load_weights(weights_path, by_name=True, skip_mismatch=True) #------------------------------------------------------# # 在这个地方设置损失,将网络的输出结果传入loss函数 # 把整个模型的输出作为loss #------------------------------------------------------# y_true = [Input(shape=(input_height//{0:32, 1:16, 2:8}[l], input_width//{0:32, 1:16, 2:8}[l], \ num_anchors//3, class_num+5)) for l in range(3)] loss_input = [*model_body.output, *y_true] model_loss = Lambda(yolo_loss, output_shape=(1, ), name='yolo_loss', arguments={ 'anchors': self.anchors, 'num_classes': class_num, 'ignore_thresh': 0.5, 'label_smoothing': label_smoothing, 'normalize': normalize })(loss_input) model = Model([model_body.input, *y_true], model_loss) return model
# mosaic 马赛克数据增强 True or False # Cosine_scheduler 余弦退火学习率 True or False # label_smoothing 标签平滑 0.01以下一般 如0.01、0.005 #------------------------------------------------------# mosaic = True Cosine_scheduler = False label_smoothing = 0 #------------------------------------------------------# # 创建yolo模型 #------------------------------------------------------# image_input = Input(shape=(None, None, 3)) h, w = input_shape print('Create YOLOv4 model with {} anchors and {} classes.'.format( num_anchors, num_classes)) model_body = yolo_body(image_input, num_anchors // 3, num_classes) #------------------------------------------------------# # 载入预训练权重 #------------------------------------------------------# print('Load weights {}.'.format(weights_path)) model_body.load_weights(weights_path, by_name=True, skip_mismatch=True) #------------------------------------------------------# # 在这个地方设置损失,将网络的输出结果传入loss函数 # 把整个模型的输出作为loss #------------------------------------------------------# y_true = [Input(shape=(h//{0:32, 1:16, 2:8}[l], w//{0:32, 1:16, 2:8}[l], \ num_anchors//3, num_classes+5)) for l in range(3)] loss_input = [*model_body.output, *y_true] model_loss = Lambda(yolo_loss,
def load_yolo(self): model_path = os.path.expanduser(self.model_path) assert model_path.endswith('.h5'), 'Keras model or weights must be a .h5 file.' self.class_names = self.get_class() self.anchors = self.get_anchors() num_anchors = len(self.anchors) num_classes = len(self.class_names) # Generate colors for drawing bounding boxes. hsv_tuples = [(x / len(self.class_names), 1., 1.) for x in range(len(self.class_names))] self.colors = list(map(lambda x: colorsys.hsv_to_rgb(*x), hsv_tuples)) self.colors = list( map(lambda x: (int(x[0] * 255), int(x[1] * 255), int(x[2] * 255)), self.colors)) # self.sess = K.get_session() # Load model, or construct model and load weights. self.yolo_model = yolo_body(Input(shape=(608, 608, 3)), num_anchors//3, num_classes) self.yolo_model.summary() # Read and convert darknet weight print('Loading weights.') weights_file = open(self.weights_path, 'rb') major, minor, revision = np.ndarray( shape=(3, ), dtype='int32', buffer=weights_file.read(12)) if (major*10+minor)>=2 and major<1000 and minor<1000: seen = np.ndarray(shape=(1,), dtype='int64', buffer=weights_file.read(8)) else: seen = np.ndarray(shape=(1,), dtype='int32', buffer=weights_file.read(4)) print('Weights Header: ', major, minor, revision, seen) convs_to_load = [] bns_to_load = [] for i in range(len(self.yolo_model.layers)): layer_name = self.yolo_model.layers[i].name if layer_name.startswith('conv2d_'): convs_to_load.append((int(layer_name[7:]), i)) if layer_name.startswith('batch_normalization_'): bns_to_load.append((int(layer_name[20:]), i)) convs_sorted = sorted(convs_to_load, key=itemgetter(0)) bns_sorted = sorted(bns_to_load, key=itemgetter(0)) print('conv2d layers: ', len(convs_to_load)) print('batch_normalization_ layers: ', len(bns_to_load)) bn_index = 0 for i in range(len(convs_sorted)): print('Converting ', i) if i == 93 or i == 101 or i == 109: #no bn, with bias weights_shape = self.yolo_model.layers[convs_sorted[i][1]].get_weights()[0].shape bias_shape = self.yolo_model.layers[convs_sorted[i][1]].get_weights()[0].shape[3] filters = bias_shape size = weights_shape[0] darknet_w_shape = (filters, weights_shape[2], size, size) weights_size = np.product(weights_shape) conv_bias = np.ndarray( shape=(filters, ), dtype='float32', buffer=weights_file.read(filters * 4)) conv_weights = np.ndarray( shape=darknet_w_shape, dtype='float32', buffer=weights_file.read(weights_size * 4)) conv_weights = np.transpose(conv_weights, [2, 3, 1, 0]) self.yolo_model.layers[convs_sorted[i][1]].set_weights([conv_weights, conv_bias]) else: #with bn, no bias weights_shape = self.yolo_model.layers[convs_sorted[i][1]].get_weights()[0].shape size = weights_shape[0] bn_shape = self.yolo_model.layers[bns_sorted[bn_index][1]].get_weights()[0].shape filters = bn_shape[0] darknet_w_shape = (filters, weights_shape[2], size, size) weights_size = np.product(weights_shape) conv_bias = np.ndarray( shape=(filters, ), dtype='float32', buffer=weights_file.read(filters * 4)) bn_weights = np.ndarray( shape=(3, filters), dtype='float32', buffer=weights_file.read(filters * 12)) bn_weight_list = [ bn_weights[0], # scale gamma conv_bias, # shift beta bn_weights[1], # running mean bn_weights[2] # running var ] self.yolo_model.layers[bns_sorted[bn_index][1]].set_weights(bn_weight_list) print(weights_size) conv_weights = np.ndarray( shape=darknet_w_shape, dtype='float32', buffer=weights_file.read(weights_size * 4)) conv_weights = np.transpose(conv_weights, [2, 3, 1, 0]) self.yolo_model.layers[convs_sorted[i][1]].set_weights([conv_weights]) bn_index += 1 weights_file.close() self.yolo_model.save(self.model_path)