本次数据训练依然使用特定书法字体识别作为目的进行训练自定义模型操作。
上节中【PaddleOCR数据集生成和图片半自动标注】提到对数据进行标注,标注最重要的是2个作用,其一是用作文本检测模型数据,二是为训练自定义数据提供数据源,标注好数据以后需要将调整过后的识别结果进行导出,得到rec_gt.txt和crop_image。
步骤 1. 指定需要生成汉字的数据(有内置的,需要自定义则需要提供) 2.下载PaddleOCR源码,并安装依赖 3.下载一个已经预训练的模型 4.整理数据集结构,调整训练配置文件 5.启动训练 6.结果验证 7.遇到的问题
1. 指定需要生成汉字的数据(有内置的,需要自定义则需要提供)
这里我们不使用内置数据,为了方便体验重新创建一个一个文件指定一些汉字作为Demo数据集,创建一个文件char_source.txt,文件中一个汉字作为一行,如:
土 下 二 丰 八 六 才 山 厂 一 十
内置的中文字典位置:./PaddleOCR/ppocr/utils/dict/chinese_cht_dict.txt
2.下载PaddleOCR源码,并安装依赖
这里推荐使用源码运行方式,方便有问题debug和调整。
项目git地址:https://github.com/PaddlePaddle/PaddleOCR.git
直接使用git clone下来,并且通过pip进行安装requirements.txt中依赖
git clone https://github.com/PaddlePaddle/PaddleOCR.git cd PaddleOCR pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple
3.下载一个已经预训练的模型
这里我们不从头开始组网,因为官方提供的神经网络结构已经相对优化,直接使用官方提供的预训练模型进行迁移学习即可。为了后续训练数据方便管理,在PaddleOCR分别创建文件夹:
存放训练模型:/train/pretrained_model/rec/
存放训练数据:/train/train_data/rec/
存放训练后模型:/train/train_model/rec
预训练模型下载地址:https://github.com/PaddlePaddle/PaddleOCR/blob/release/2.5/doc/doc_ch/models_list.md
这里我们采用【ch_PP-OCRv3_det】中文检测预训练模型进行训练,下载预训练模型

为了方便管理,将下载成功的训练模型放入 PaddleOCR/train/pretrained_model/rec/ 中
4.整理数据集结构,调整训练配置文件
4.1 整理数据结构
进行模型训练数据结构一定要求,层级关系按官方要求的来,如下:
|-train_data |-rec |- rec_gt_train.txt |- crop_img |- 一.png |- 二.jpg |- 熵.jpg | ...

这里要特别数据数据编码问题在window上,utf8 与 utf8-sign是不一样的,主要体现在rec_gt_train.txt问中,其每行内容组成为:图片名称+’\t‘+lable+’\n’
在window上尝试通过python来生成该文件,最后发现要么多出了 \r\n 要么多出理论\x0efff等制表符,所以这里最好是使用PPOCRLabel工具导出较好,避免个数据读取的各种错误。
4.2 调整训练配置文件
项目提供了很多配置文件的模版,位于configs目录下。这里我们采用“/configs/rec/PP-OCRv3/ch_PP-OCRv3_rec.yml”配置模版,复制出来一个,并且命名为“my_ch_PP-OCRv3_rec.yml”,修改文件:
Global: debug: true use_gpu: false #测试不使用gpu epoch_num: 50 #训练50次 log_smooth_window: 20 print_batch_step: 3 #训练多次持打印下结果 save_model_dir: ./train/train_model/rec/rec_ppocr_v3 #保存训练后的模型文件目标 save_epoch_step: 3 #训练多少次保存下模型 eval_batch_step: [0, 10] #从多少次开始,每格10次就做一次验证 cal_metric_during_train: true pretrained_model: ./train/pretrained_model/rec/ch_PP-OCRv3_rec_train/best_accuracy #指定预训练模型的地址 checkpoints: save_inference_dir: use_visualdl: true #是否开启可视化 infer_img: ./train/train_data/rec/crop_img/一_9_crop_0.jpg #验证图片 character_dict_path: ppocr/utils/ppocr_keys_v1.txt #字典位置,这里直接使用内置的字典 max_text_length: &max_text_length 5 #文本最长 infer_mode: false use_space_char: true distributed: true save_res_path: ./train/train_model/rec/rec_ppocr_v3/predicts_ppocrv3.txt Optimizer: name: Adam #学习算法 beta1: 0.9 beta2: 0.999 lr: name: Cosine learning_rate: 0.001 #学习率 warmup_epoch: 5 regularizer: name: L2 factor: 3.0e-05 Architecture: model_type: rec algorithm: SVTR Transform: Backbone: name: MobileNetV1Enhance scale: 0.5 last_conv_stride: [1, 2] last_pool_type: avg Head: name: MultiHead head_list: - CTCHead: Neck: name: svtr dims: 64 depth: 2 hidden_dims: 120 use_guide: True Head: fc_decay: 0.00001 - SARHead: enc_dim: 512 max_text_length: *max_text_length Loss: name: MultiLoss loss_config_list: - CTCLoss: - SARLoss: PostProcess: name: CTCLabelDecode Metric: name: RecMetric main_indicator: acc ignore_space: False Train: dataset: name: SimpleDataSet #这里使用SimpleDataSet数据格式,也就是上面我们说的数据结构,还支持LMDBDataSet数据格式 data_dir: ./train/train_data/rec/ #文件基本路径 ext_op_transform_idx: 1 label_file_list: - ./train/train_data/rec/rec_gt_train.txt #资源标签路径 transforms: - DecodeImage: img_mode: BGR channel_first: false - RecConAug: prob: 0.5 ext_data_num: 2 image_shape: [32, 32, 3] #图像增强大小,这里使用32*32,如果有其他尺寸,需要修改对应backbone特征提取层的stride步长大小 - RecAug: - MultiLabelEncode: - RecResizeImg: image_shape: [3, 32, 32] #将图像resiez到 32*32 - KeepKeys: keep_keys: - image - label_ctc - label_sar - length - valid_ratio loader: shuffle: true batch_size_per_card: 26 #每次数据集大小 drop_last: true num_workers: 4 #线程数 Eval: dataset: name: SimpleDataSet data_dir: ./train/train_data/rec/ #验证集数据文件根目录 label_file_list: - ./train/train_data/rec/rec_gt_test.txt #验证集的数据局 transforms: - DecodeImage: img_mode: BGR channel_first: false - MultiLabelEncode: - RecResizeImg: image_shape: [3, 32, 32] - KeepKeys: keep_keys: - image - label_ctc - label_sar - length - valid_ratio loader: shuffle: false drop_last: false batch_size_per_card: 26 num_workers: 4
PS:关于数据集路径要格外注意一下,data_dir的配置路径需要结合label_file_list综合判断,避免训练过程图片数据找不到,如 rec_gt_train.txt 中内容是这样的:
crop_img/目_493_crop_0.jpg 目
那么这里的 data_dir 应该是到rec就可以了,即:/train/train_data/rec/ ,框架内部会自动拼接“crop_img/目_493_crop_0.jpg”
如果 rec_gt_train.txt 中内容是这样的:
目_493_crop_0.jpg 目
那么这里的 data_dir 应该是到rec就可以了,即:/train/train_data/rec/crop_img/
5.启动训练
可以直接用PyCharm打开PaddleOCR项目,直接运行,也可以再控制台通过python运行,这里直接通过控制台来运行。
#打开控制台,并且激活paddle环境(开始在ancoda中环境的一个环境paddle_env) conda activate paddle_env #进入PaddleOCR根目录 cd PaddleOCR #开启CPU类型的训练 python3 tools/train.py -c configs/rec/PP-OCRv3/my_ch_PP-OCRv3_rec.yml #以下是开启GPU训练 #多卡训练,通过--gpus参数指定卡号 python3 -m paddle.distributed.launch --gpus '0,1,2,3' tools/train.py -c configs/rec/PP-OCRv3/my_ch_PP-OCRv3_rec.yml -o Global.pretrained_model=./train/pretrain_models/rec/ch_PP-OCRv3_rec_train/best_accuracy
启动成功后正常来说会出现以下信息基本上就是在开始训练了
ader_cost: 0.03625 s, avg_batch_cost: 1.40823 s, avg_samples: 26.0, ips: 18.46296 samples/s, eta: 0:22:13 [2022/07/17 00:14:50] ppocr INFO: epoch: [1/50], global_step: 6, lr: 0.000026, acc: 0.000000, norm_edit_dis: 0.000000, CTCLoss: 32.660141, SARLoss: 8.791344, loss: 41.452690, avg_reader_cost: 0.00044 s, avg_batch_cost: 1.19850 s, avg_samples: 26.0, ips: 21.69376 samples/s, eta: 0:20:30 [2022/07/17 00:14:54] ppocr INFO: epoch: [1/50], global_step: 9, lr: 0.000042, acc: 0.000000, norm_edit_dis: 0.000000, CTCLoss: 32.668232, SARLoss: 8.787222, loss: 41.436691, avg_reader_cost: 0.00066 s, avg_batch_cost: 1.27596 s, avg_samples: 26.0, ips: 20.37682 samples/s, eta: 0:20:17
本次训练共500张汉字图片,训练50次,验证的准确率在91%左右,一般般:
[2022/07/17 00:42:49] ppocr INFO: epoch: [50/50], global_step: 948, lr: 0.000031, acc: 0.9138755762230724, norm_edit_dis: 0.846154, CTCLoss: 0.885161, SARLoss: 0.752444, loss: 1.690192, avg_reader_cost: 0.00248 s, avg_batch_cost: 1.17414 s, avg_samples: 26.0, ips: 22.14392 samples/s, eta: 0:00:02 [2022/07/17 00:42:51] ppocr INFO: epoch: [50/50], global_step: 950, lr: 0.000030, acc: 0.9377990206268177, norm_edit_dis: 0.846154, CTCLoss: 0.822314, SARLoss: 0.752444, loss: 1.678297, avg_reader_cost: 0.00009 s, avg_batch_cost: 0.79369 s, avg_samples: 17.333333333333332, ips: 21.83885 samples/s, eta: 0:00:00
6.结果验证
接下来我们找几张图片试试模型的准确度情况,控制台使用脚本:
#找一个 “一”的汉字来测试下 python3 tools/infer_rec.py -c configs/rec/PP-OCRv3/my_ch_PP-OCRv3_rec.yml -o Global.pretrained_model=/train/train_model/rec/rec_ppocr_v3/best_accuracy Global.infer_img=/train/train_data/rec/crop_img/一_9_crop_0.jpg


可以正常识别到汉字,但是准确率很低,应该是该汉字训练不够导致
#找一个 “七” 汉字测试下准确率 python3 tools/infer_rec.py -c configs/rec/PP-OCRv3/my_ch_PP-OCRv3_rec.yml -o Global.pretrained_model=/train/train_model/rec/rec_ppocr_v3/best_accuracy Global.infer_img=/train/train_data/rec/crop_img/七_47_crop_0.jpg


“七”字准确率尚可
7.遇到的问题
7.1 No module named ‘yaml’
Traceback (most recent call last): File "/Users/fplei/Work/Study/paddle/PaddleOCR/tools/train.py", line 26, in <module> import yaml ModuleNotFoundError: No module named 'yaml'
解决:未找到解析ymal格式的插件,安装就是了
pip install pyyaml
7.2 ‘ParallelEnv’ object has no attribute ‘_device_id’
Traceback (most recent call last): File "/Users/fplei/Work/Study/paddle/PaddleOCR/tools/train.py", line 188, in <module> config, device, logger, vdl_writer = program.preprocess(is_train=True) File "/Users/fplei/Work/Study/paddle/PaddleOCR/tools/program.py", line 574, in preprocess device = 'gpu:{}'.format(dist.ParallelEnv() File "/Users/fplei/opt/anaconda3/envs/paddle_env/lib/python3.9/site-packages/paddle/fluid/dygraph/parallel.py", line 200, in device_id return self._device_id AttributeError: 'ParallelEnv' object has no attribute '_device_id'
解决:将配置文件中use_gpu改为false
Global:
use_gpu: false
其他问题整理好再更新!