Notebook建模示例
本文以物体检测任务类型为例,从启动Notebook到引入数据、训练模型,再到保存模型的全流程。
启动Notebook
step1:在左侧导航栏中选择开发->Notebook开发
step2:选择开发语言、AI框架、资源规格与工作目录后启动Notebook

训练物体检测模型
下载 PaddleDetection 套件
打开进入 Notebook,点击进入终端,本文以 PaddleDetection
代码库 release/2.3
分支为例,输入如下命令克隆PaddleDetection代码库并切换至release/2.3分支。整个过程需要数十秒,请耐心等待。
1# gitee 国内下载比较快
2git clone https://gitee.com/paddlepaddle/PaddleDetection.git -b release/2.3
3# github
4# git clone https://github.com/PaddlePaddle/PaddleDetection.git -b release/2.3
安装环境
在终端环境中,安装该版本的 PaddleDetection
代码包依赖的 paddlepaddle-gpu
,执行如下命令:
1python -m pip install paddlepaddle-gpu==2.1.3.post101 -f https://www.paddlepaddle.org.cn/whl/linux/mkl/avx/stable.html
安装完成后,使用 python
或 python3
进入python解释器,输入 import paddle
,再输入 paddle.utils.run_check()
如果出现 PaddlePaddle is installedsuccessfully!
,说明成功安装。
准备训练数据
训练数据是模型生产的重要条件,优质的数据集可以很大程度上的提升模型训练效果,准备数据可以参考链接。本文所用的安全帽检测数据集可前往此链接进行下载:下载链接。
step1:导入用户数据
目前在 Notebook 中不能直接访问您在 飞桨EasyDL 中创建的数据集,需要通过在终端输入数据所在路径。
step2:数据转换
PaddleDetection
训练所需要的数据格式与 飞桨EasyDL
默认的数据格式有所不同,所以需要利用脚本将导入的数据转为 PaddleDetection
支持的数据格式,并进行3:7切分。
PaddleDetection
默认支持的标注格式为 COCO格式
,转换脚本如下:
1import os
2import cv2
3import json
4import glob
5import codecs
6import random
7from pycocotools.coco import COCO
8
9def parse_bml_json(json_file):
10 """
11 解析标注文件
12 :return:
13 """
14 annos = json.loads(codecs.open(json_file).read())
15 labels = annos['labels']
16 bboxes = []
17 for label in labels:
18 x1 = label["x1"]
19 y1 = label["y1"]
20 x2 = label["x2"]
21 y2 = label["y2"]
22 id = label["name"]
23 bboxes.append([x1, y1, x2, y2, id])
24 return bboxes
25
26
27
28
29
30def bbox_transform(box):
31 """
32 x1, y1, x2, y2 转为 x1, y1, width, height
33 :return
34 """
35 box = list(map(lambda x: float(x), box))
36 box[2] = box[2] - box[0]
37 box[3] = box[3] - box[1]
38 return box
39
40
41
42
43
44def parse_label_list(src_data_dir, save_dir):
45 """
46 遍历标注文件,获取label_list
47 :return:
48 """
49 label_list = []
50 anno_files = glob.glob(src_data_dir + "*.json")
51 for anno_f in anno_files:
52 annos = json.loads(codecs.open(anno_f).read())
53 for lb in annos["labels"]:
54 label_list.append(lb["name"])
55 label_list = list(set(label_list))
56 with codecs.open(os.path.join(save_dir, "label_list.txt"), 'w', encoding="utf-8") as f:
57 for id, label in enumerate(label_list):
58 f.writelines("%s:%s\n" % (id, label))
59 return len(label_list), label_list
60
61
62
63
64
65def bml2coco(src_dir, coco_json_file):
66 """
67 将标注格式转为COCO标注格式
68 :return:
69 """
70 coco_images = []
71 coco_annotations = []
72
73 image_id = 0
74 anno_id = 0
75 image_list = glob.glob(src_dir + "*.[jJPpBb][PpNnMm]*")
76 for image_file in image_list:
77 anno_f = image_file.split(".")[0] + ".json"
78 if not os.path.isfile(anno_f):
79 continue
80 bboxes = parse_bml_json(anno_f)
81 im = cv2.imread(image_file)
82 h, w, _ = im.shape
83 image_i = {"file_name": os.path.basename(image_file), "id": image_id, "width": w, "height": h}
84 coco_images.append(image_i)
85 for id, bbox in enumerate(bboxes):
86 # bbox : [x1, y1, x2, y2, label_name]
87 anno_i = {"image_id": image_id, "bbox": bbox_transform(bbox[:4]), 'category_id': label_list.index(bbox[4]),
88 'id': anno_id, 'area': 1.1, 'iscrowd': 0, "segmentation": None}
89 anno_id += 1
90 coco_annotations.append(anno_i)
91
92 image_id += 1
93
94 coco_categories = [{"id": id, "name": label_name} for id, label_name in enumerate(label_list)]
95 coco_dict = {"info": "info", "licenses": "BMLCloud", "images": coco_images, "annotations": coco_annotations,
96 "categories": coco_categories}
97 with open(coco_json_file, 'w', encoding="utf-8") as fin:
98 json.dump(coco_dict, fin, ensure_ascii=False)
99
100
101
102
103
104def split_det_origin_dataset(
105 origin_file_path,
106 train_file_path,
107 eval_file_path,
108 ratio=0.7):
109 """
110 按比例切分物体检测原始数据集
111 :return:
112 """
113 coco = COCO(origin_file_path)
114 img_ids = coco.getImgIds()
115 items_num = len(img_ids)
116 train_indexes, eval_indexes = random_split_indexes(items_num, ratio)
117 train_items = [img_ids[i] for i in train_indexes]
118 eval_items = [img_ids[i] for i in eval_indexes]
119
120 dump_det_dataset(coco, train_items, train_file_path)
121 dump_det_dataset(coco, eval_items, eval_file_path)
122
123 return items_num, len(train_items), len(eval_items)
124
125
126
127
128
129def random_split_indexes(items_num, ratio=0.7):
130 """
131 按比例分割整个list的index
132 :return:分割后的两个index子列表
133 """
134 offset = round(items_num * ratio)
135 full_indexes = list(range(items_num))
136 random.shuffle(full_indexes)
137 sub_indexes_1 = full_indexes[:offset]
138 sub_indexes_2 = full_indexes[offset:]
139
140 return sub_indexes_1, sub_indexes_2
141
142
143
144
145
146def dump_det_dataset(coco, img_id_list, save_file_path):
147 """
148 物体检测数据集保存
149 :return:
150 """
151 imgs = coco.loadImgs(img_id_list)
152 img_anno_ids = coco.getAnnIds(imgIds=img_id_list, iscrowd=0)
153 instances = coco.loadAnns(img_anno_ids)
154 cat_ids = coco.getCatIds()
155 categories = coco.loadCats(cat_ids)
156 common_dict = {
157 "info": coco.dataset["info"],
158 "licenses": coco.dataset["licenses"],
159 "categories": categories
160 }
161 img_dict = {
162 "image_nums": len(imgs),
163 "images": imgs,
164 "annotations": instances
165 }
166 img_dict.update(common_dict)
167
168 json_file = open(save_file_path, 'w', encoding='UTF-8')
169 json.dump(img_dict, json_file)
170
171
172
173
174
175class_nums, label_list = parse_label_list("/home/work/data/${dataset_id}/", "/home/work/PretrainedModel/")
176bml2coco("/home/work/data/${dataset_id}/", "/home/work/PretrainedModel/org_data_list.json")
177split_det_origin_dataset("/home/work/PretrainedModel/org_data_list.json", "/home/work/PretrainedModel/train_data_list.json", "/home/work/PretrainedModel/eval_data_list.json")
将上述脚本存放为 convert.py
代码脚本,并将脚本最后两行的 "/home/work/data/${dataset_id}/"
均替换为所指定数据集路劲,在终端中运行即可。 运行代码。
1python covert.py
注意:如果报错
No module named 'pycocotools'
,需要通过如下命令安装相关依赖包,再运行covert.py
代码。
1pip install pycocotools
运行 covert.py
代码成功之后将在 PretrainedModel/
文件夹下生成对应的数据文件,包括 label_list.txt
、train_data_list.json
、eval_data_list.json
、org_data_list.json
。
训练模型
开发者准备好训练数据和安装环境之后即可开始训练物体检测模型。
step1:在终端中打开 PaddleDetection
目录
1cd /PaddleDetection
step2:修改yaml配置文件
在PaddleDetection 2.0后续版本,采用了模块解耦设计,用户可以组合配置模块实现检测器,并可自由修改覆盖各模块配置,本文以 configs/yolov3/yolov3_darknet53_270e_coco.yml
为例:
1yolov3_darknet53_270e_coco.yml 主配置入口文件
2coco_detection.yml 主要说明了训练数据和验证数据的路径
3runtime.yml 主要说明了公共的运行参数,比如说是否使用GPU、每多少个epoch存储checkpoint等
4optimizer_270e.yml 主要说明了学习率和优化器的配置。
5yolov3_darknet53.yml 主要说明模型、和主干网络的情况。
6yolov3_reader.yml 主要说明数据读取器配置,如batch size,并发加载子进程数等,同时包含读取后预处理操作,如resize、数据增强等等
需要修改/覆盖的参数均可写在主配置入口文件中,主要修改点为训练、验证数据集路径、运行epoch数、学习率等,修改后的主配置文件如下(注释行即为需要修改的点):
1_BASE_: [
2 '../datasets/coco_detection.yml',
3 '../runtime.yml',
4 '_base_/optimizer_270e.yml',
5 '_base_/yolov3_darknet53.yml',
6 '_base_/yolov3_reader.yml',
7]
8
9snapshot_epoch: 5
10weights: output/yolov3_darknet53_270e_coco/model_final
11
12# 预训练权重地址
13pretrain_weights: https://paddledet.bj.bcebos.com/models/yolov3_darknet53_270e_coco.pdparams
14
15# coco_detection.yml
16num_classes: 2 #实际类别数
17TrainDataset:
18 !COCODataSet
19 image_dir: data/${dataset_id}/ # 图片地址
20 anno_path: PretrainedModel/train_data_list.json # 标注文件
21 dataset_dir: /home/work/ # 数据集根目录
22 data_fields: ['image', 'gt_bbox', 'gt_class', 'is_crowd']
23
24EvalDataset:
25 !COCODataSet
26 image_dir: data/${dataset_id}/ # 图片地址
27 anno_path: PretrainedModel/eval_data_list.json # 标注文件
28 dataset_dir: /home/work/ # 数据集根目录
29
30# optimizer_270e.yml
31epoch: 50 # 迭代轮数
32LearningRate:
33 base_lr: 0.0001 # 学习率
34 schedulers:
35 - !PiecewiseDecay
36 gamma: 0.1
37 milestones:
38 - 30
39 - 45
40 - !LinearWarmup
41 start_factor: 0.
42 steps: 400
step3:训练模型
在终端中执行以下命令,开始模型训练。
1cd /PaddleDetection/
2python tools/train.py -c configs/yolov3/yolov3_darknet53_270e_coco.yml --eval
注意:如果报错 No module named 'lap'
和 No module named 'motmetrics'
,则需要通过如下命令安装相关依赖包,再运行 coversion.py
代码。(如果缺失其他模块,也可用类似命令下载安装)
1pip install lap motmetrics
step4:模型评估
在终端中执行以下命令,开始模型评估。
1python tools/eval.py -c configs/yolov3/yolov3_darknet53_270e_coco.yml \
2 -o weights=output/yolov3_darknet53_270e_coco/model_final
运行完成输出如下结果:
step5:模型预测
在终端中执行以下命令,开始模型预测(注意修改图片路径)。
1python tools/infer.py -c configs/yolov3/yolov3_darknet53_270e_coco.yml \
2 --infer_img=/home/work/data/${task_id}/xxx.jpeg \
3 --output_dir=infer_output/ \
4 --draw_threshold=0.5 \
5 -o weights=output/yolov3_darknet53_270e_coco/model_final
step6:导出模型
在终端中执行以下命令,将最佳模型转为可以用于发布的 inference 模型
1python tools/export_model.py -c configs/yolov3/yolov3_darknet53_270e_coco.yml \
2 --output_dir=/home/work/PretrainedModel/ \
3 -o weights=output/yolov3_darknet53_270e_coco/model_final
在终端中执行以下命令,将导出模型移至 /PretrainedModel/
目录。
1mv /PretrainedModel/yolov3_darknet53_270e_coco/* /home/work/PretrainedModel/