目录
在上一篇文章中,构建好了paddleOCR 运行必需的环境,并通过在线下载的方式,使用官方训练好的模型进行了简单的部署预测。但现实使用中,对于特定任务的数据集,如果想要提高精度表现,需要在原始模型的基础上进行训练微调。
因此,本文记录如何构建符合paddlepaddle训练要求格式的数据集,以及如何使用官方提供的便利低代码量平台 PaddleX 进行模型训练。
环境篇文章快速链接:https://blog.csdn.net/qq_58718853/article/details/142875253
本文属于是记录性文档,斗胆抛砖引玉,详细参见官方文档地址:https://gitee.com/paddlepaddle/PaddleX/blob/release/3.0-beta1/docs/module_usage/tutorials/ocr_modules/text_detection.md
一、自建数据集
1.官方数据集格式参考
在上篇文章中介绍了官方测试数据的命令行快速下载和解压。首先下载官方数据,查看其数据集构建目录结构和内容编写规范。
python
## 下载解压数据集
wget https://paddle-model-ecology.bj.bcebos.com/paddlex/data/ocr_det_dataset_examples.tar -P ./dataset
tar -xf ./dataset/ocr_det_dataset_examples.tar -C ./dataset/
目录结构上,在数据集目录下放 images子目录存放所有的图片,框和文字信息分为训练 train和 val 验证,分别存放在 txt 文件中。
txt 文件编写上 ,文本文件每一行代表一张图片的所有信息------图片名和地址、所有框和文字信息的列表。具体来说,框信息和文字信息一起存放在字典结构中,一张图存在多个框和字组合,一起存放在一个列表中。
图片地址和框信息中间用 **'\t'**分隔,中间不能出现空格。图片地址信息始终是字符串格式,需特别注意的是框和文字信息的编写,存在从字典列表结构写入txt 文本结构的转化细节,这在后续实操中会解释。
综上,自建数据集实际需要操作的部分是构建这个两个关键 txt 文件,而编写文本文件中的关键就是后面框和文本信息的编写。下面我自己编写了一个简单的功能性脚本,可以完成对txt文件的编写。
2.自建数据集txt文件编写代码
代码总览:
直接运行下述代码会在项目目录下新建示例文件 test.txt 。
python
import json
import os
class Paddle_Dataset_Creator:
def __init__(self, savefile, input_dict, input_num=4, mode='only_det'):
self.savefile = savefile # paddle训练数据保存地址
self.input_num = input_num # 输入训练框数量信息:==4------左上、右下两点四坐标 or ==8------四顶点八坐标
self.input_dict = input_dict # 输入字典:键------文件名;值:框坐标列表
self.mode = mode # 选择模式:only_det------只进行检测框的训练集构建; ocr------检测框和区域识别字训练集
self.pp_boxdict = None # 存放格式正确的框字典
# 四坐标转为八坐标,并保存paddle支持的框列表结构
def check_box(self):
# 标准格式------以一个框为例:[【xx,xx】,【xx,xx】,【xx,xx】,【xx,xx】],从左上顶点出发,顺时针一圈
if self.input_num == 4:
self.pp_boxdict = dict()
for key in self.input_dict.keys():
two_boxes_list = self.input_dict[key] # 四坐标列表信息
pp_box_list = []
for two_box in two_boxes_list:
pp_dict = dict()
if self.mode == 'only_det':
l,t,r,b = two_box # 左x_min,上y_min, 右x_max, 下y_max
pp_dict["transcription"] = "ZW"
elif self.mode == 'ocr':
l,t,r,b,text = two_box
pp_dict["transcription"] = str(text)
else:
raise ValueError('miss key value self.mode')
pp_box = [[min(l,r), min(t,b)], [max(l,r), min(t,b)], [max(l,r), max(t,b)], [min(l,r), max(t,b)]]
pp_dict["points"] = pp_box
pp_box_list.append(pp_dict)
self.pp_boxdict[key] = pp_box_list
elif self.input_num == 8:
self.pp_boxdict = dict()
for key in self.input_dict.keys():
four_boxes_list = self.input_dict[key] # 四坐标列表信息
pp_box_list = []
for four_box in four_boxes_list:
pp_dict = dict()
if self.mode == 'only_det':
pp_dict["transcription"] = "ZW"
pp_dict["points"] = four_box
elif self.mode == 'ocr':
pp_dict["transcription"] = str(four_box[4])
pp_dict["points"] = four_box[:4]
else:
raise ValueError('miss key value self.mode')
pp_box_list.append(pp_dict)
self.pp_boxdict[key] = pp_box_list
else:
raise ValueError('cant process box_num, box_num must in [4,8]')
# 创建paddle数据txt文件
def create_pptext(self, mode='train'):
savedir = os.path.join(self.savefile, mode+'.txt') # 保存结果地址
if self.pp_boxdict != None:
for name in self.pp_boxdict.keys():
filename = 'images/'+name # 写入txt图片地址信息
box_list = self.pp_boxdict[name] # 写入txt框和字信息
json_box_list = json.dumps(box_list, ensure_ascii=False, separators=(',',':'))
line_text = filename + '\t' + str(json_box_list) # 写入一行完整信息,中间使用'\t'隔开
with open(savedir, 'a') as f:
f.writelines(str(line_text))
with open(savedir, 'a') as f:
f.write('\n')
if __name__=='__main__':
example1 = {'abc.jpg':[[1,2,3,4],[5,6,7,8]], 'def.jpg':[[10,20,30,40],[50,60,70,80]]}
example2 = {'abc.jpg':[[1,2,3,4,'a'],[5,6,7,8,'b']], 'def.jpg':[[10,20,30,40,'c'],[50,60,70,80,'d']]}
paddle_creator = Paddle_Dataset_Creator(savefile='./', input_dict=example1, input_num=4, mode='only_det')
paddle_creator.check_box()
paddle_creator.create_pptext(mode='test')
print(paddle_creator.pp_boxdict)
使用方法:
必要条件:1.框信息是顶点的绝对值坐标信息构建的(如果是归一化坐标------YOLO,或者是左上点坐标信息加框的长宽,需要先做好数据转化)
2.输入数据格式必须是字典,且键为对应图片文件名,值为该图所有框和字信息
3.如果存在文字信息,请放在对应框列表的最后;如果没有文字信息,则默认为只训练框的检测模型。
具体使用:
具体使用的时候,只需将此类嵌入文件处理的过程中,使用相应的功能函数即可。
①初始化 self.init:
初始化类有四个需要输入的参数------savefile :你需要txt文件保存的地址;input_dict :框和文字信息字典(按必要条件要求组织);input_num :框信息坐标数量,默认是4,代表左上右下两点四坐标;mode :是做仅框的检测模型训练 'only_det' ,还是带上识别模型的文本训练**'ocr'**
②框信息规范 self.check_box:
直接训练该函数会将输入的框信息标准化为paddle需要的格式
③写入txt文件 self.create_pptext(mode):
传入mode参数代表当前编写的是训练集train的txt还验证val的txt文件。
3.数据集检验
PaddleX 中自备了检验数据集是否构建成功的命令行指令。
使用时只需将 xxx.yaml 修改为自建模型配置文件地址,将dataset_dir=xxx 改为自建数据集地址即可。
python
# 效验官方数据集
python main.py -c paddlex/configs/text_detection/PP-OCRv4_mobile_det.yaml -o Global.mode=check_dataset -o Global.dataset_dir=./dataset/ocr_det_dataset_examples
# 效验自建数据集
python main.py -c xxx.yaml -o Global.mode=check_dataset -o Global.dataset_dir=xxx
运行出现以下绿字则说明数据集构建成功。
二、模型训练
这里模型训练仅以文本检测 ------text_detection 模型为例,实际上大部分其他模型的训练方式逻辑和本例类似。两步走:一、找到对应模型配置文件;二、命令行指令运行训练。
1.模型配置yaml文件
首先需要找到需要的模型配置 yaml 文件,在之前git克隆下载好的 PaddleX 源码**/paddlex/configs**目录下就可以查询到 paddle 所有模型的配置文件。
打开本例需要的PP-OCRv4_server_det.yaml文件,按下图修改一些参数即可。(实际上,不一定非要修改,在命令行指令运行中也可以传入修改对应参数,如在命令代码后加上-o Global.dataset_dir=./dataset/ocr_det_dataset_examples,也可以修改数据集目录)
2.命令行指令训练
命令行训练需要配置几个所必需的参数,下面逐一记录。
一个官方例子如下图。
基础命令参数配置:
**① -c model.yaml:**这是模型配置yaml文件地址
②-o Global.mode=train:当前模式选择,可以是训练train模式也可以是验证或者预测模式
③-o Global.dataset_dir=./:之前构建的训练数据集目录地址
④-o Global.device=gpu:0,1:指定训练设备,例中表示使用双卡训练
⑤-o Global.output=./:结果保存地址
训练参数配置:
⑥-o Train.epochs_iters=100:训练轮次
⑦-o Train.num_classes=1:数据集中的类别数,对于仅框检测来说,类别为1
⑧-o Train.batch_size=16:训练批量大小
⑨-o Train.pretrain_weight_path:预训练模型参数地址,第一次训练会下载在本地c盘
参数配置上的详细内容参考官方文档地址:https://gitee.com/paddlepaddle/PaddleX/blob/release/3.0-beta1/docs/module_usage/instructions/config_parameters_common.md
训练中会打印过程结果。
经过训练结果保存目录会得到以下结果。
可以在best_model下找到训练最优模型参数,即可将微调模型参数用于部署任务。
由于服务器CUDA版本环境存在一定冲突,虽然之前在yolo训练时没有报过错,但paddle会有警告。不过似乎并特别影响正常训练,训练还是能跑起来的。下一章将集中精力解决这些环境报错,并深入研究其训练输出目录下结果的使用,还有模型的测试评估和最终的部署。