[PaddlePaddle/PaddleOCR]rec_svtr_large_ch识别模型, loss不下降问题

2024-05-13 866 views
1

模型: rec_svtr_large_ch 训练集数量:580W (vocab字符数量7720,简体 + 繁体)

问题描述: 训练了大概3-4个epoch后,继续多次调整learning rate至0.000004,batch size至32,训了了一个epoch loss都无法继续下降(loss保持在1.8 - 2.3左右波动),验证集acc在也没有提升。

问题:

  1. 请问针对svtr large模型,batch size和learning rate一般可以最低设置多少可以有效训练?
  2. 我怀疑是我的训练集有问题,因为我的训练集有长文本和超短文本(甚至单个字)所以图片size差别很大(如下图),请问这样设置是否合理?是否需要在控制在(32,320)上下才能有效训练否则无法收敛吗? image

image

image

image

非常感谢百度Paddle团队带来的开源技术,也谢谢帮忙解答!

回答

1

模型: rec_svtr_large_ch 训练集数量:580W (vocab字符数量7720,简体 + 繁体)

问题描述: 训练了大概3-4个epoch后,继续多次调整learning rate至0.000004,batch size至32,训了了一个epoch loss都无法继续下降(loss保持在1.8 - 2.3左右波动),验证集acc在也没有提升。

问题:

  1. 请问针对svtr large模型,batch size和learning rate一般可以最低设置多少可以有效训练?
  2. 我怀疑是我的训练集有问题,因为我的训练集有长文本和超短文本(甚至单个字)所以图片size差别很大(如下图),请问这样设置是否合理?是否需要在控制在(32,320)上下才能有效训练否则无法收敛吗? image

image

image

image

非常感谢百度Paddle团队带来的开源技术,也谢谢帮忙解答!

另外这是我的配置文件

Global: use_gpu: True epoch_num: 2 log_smooth_window: 100 print_batch_step: 100 save_model_dir: ./output/rec/rec_svtr_large_ch/ save_epoch_step: 1

evaluation is run every 2000 iterations after the 0th iteration

eval_batch_step: [0, 10000] cal_metric_during_train: True pretrained_model: ./output/rec/rec_svtr_large_ch/best_accuracy checkpoints: save_inference_dir: use_visualdl: False infer_img: doc/imgs_words/ch/word_1.jpg

for data or label process

character_dict_path: vocab.txt max_text_length: 40 infer_mode: False use_space_char: True save_res_path: ./output/rec/predicts_svtr_large_ch.txt

Optimizer: name: AdamW beta1: 0.9 beta2: 0.99 epsilon: 0.00000008 weight_decay: 0.05 no_weight_decay_name: norm pos_embed one_dim_param_no_weight_decay: true lr: name: Cosine learning_rate: 0.000004 warmup_epoch: 0

Architecture: model_type: rec algorithm: SVTR Transform: name: STN_ON tps_inputsize: [32, 64] tps_outputsize: [32, 320] num_control_points: 20 tps_margins: [0.05,0.05] stn_activation: none Backbone: name: SVTRNet img_size: [32, 320] out_char_num: 40 out_channels: 384 patch_merging: 'Conv' embed_dim: [192, 256, 512] depth: [3, 9, 9] num_heads: [6, 8, 16] mixer: ['Local','Local','Local','Local','Local','Local','Local','Local','Local','Local','Global','Global','Global','Global','Global','Global','Global','Global','Global','Global','Global'] local_mixer: [[7, 11], [7, 11], [7, 11]] prenorm: False Neck: name: SequenceEncoder encoder_type: reshape Head: name: CTCHead

Loss: name: CTCLoss

PostProcess: name: CTCLabelDecode

Metric: name: RecMetric main_indicator: acc

Train: dataset: name: SimpleDataSet data_dir: /home/aistudio/text_renderer/output/TCSynth_raw label_file_list: /home/aistudio/text_renderer/output/TCSynth_raw/train.txt transforms:

  • DecodeImage: # load image img_mode: BGR channel_first: False
  • CTCLabelEncode: # Class handling label
  • SVTRRecResizeImg: image_shape: [3, 32, 320] padding: False
  • KeepKeys: keep_keys: ['image', 'label', 'length'] # dataloader will return list in this order loader: shuffle: True batch_size_per_card: 48 drop_last: True num_workers: 12

Eval: dataset: name: SimpleDataSet data_dir: /home/aistudio/text_renderer/output/label/ label_file_list: /home/aistudio/text_renderer/output/label/label.txt transforms:

  • DecodeImage: # load image img_mode: BGR channel_first: False
  • CTCLabelEncode: # Class handling label
  • SVTRRecResizeImg: image_shape: [3, 32, 320] padding: False
  • KeepKeys: keep_keys: ['image', 'label', 'length'] # dataloader will return list in this order loader: shuffle: False drop_last: False batch_size_per_card: 64 num_workers: 2
7

还有一个疑问是关于模型轻量化的,针对SVTR large model,paddleSlim进行转换后(好像是转int8),一般精度会有多少损失,能带来多大的性能提升呢?我看Demo,使用paddleSlim导出模型前需要先进行量化训练,但是量化训练非常的慢,所以目前还没有尝试,请问这个量化训练是必要的吗?需要进行多少epoch的量化训练?

7

@vance-coder 非官方人员,Cosine是余弦策略,你的学习率是否设置太小了?并且,你也没有给出你训练使用的设备,多卡,batch_size和单卡学习率设置是不一样的,你的示例文本中,有倾斜的文本,建议增加一个cls模型,或者加一个弱监督模型用于文本矫正; 另: 1,不确定学习率设置多少,可以先尝试使用Piecewise策略 2,通过ocr_v3的蒸馏模型进行微调感觉在你这个场景下有更好的效果 3,训练loss在前几个EPOCH波动属于正常情况,建议贴出日志/visual_dl的训练过程,ACC和norm_edit_dis的变化情况如何? 4,paddleSlim的模型量化未使用过,不做评论

5

@vance-coder 非官方人员,Cosine是余弦策略,你的学习率是否设置太小了?并且,你也没有给出你训练使用的设备,多卡,batch_size和单卡学习率设置是不一样的,你的示例文本中,有倾斜的文本,建议增加一个cls模型,或者加一个弱监督模型用于文本矫正; 另: 1,不确定学习率设置多少,可以先尝试使用Piecewise策略 2,通过ocr_v3的蒸馏模型进行微调感觉在你这个场景下有更好的效果 3,训练loss在前几个EPOCH波动属于正常情况,建议贴出日志/visual_dl的训练过程,ACC和norm_edit_dis的变化情况如何? 4,paddleSlim的模型量化未使用过,不做评论

谢谢解答 我使用的百度提供的AIStudio平台训练的,一般是用V100 32G环境

  1. 我尝试过0.00001的学习率,但是一样无法下降,而且验证集的accuracy波动较大,所以才尝试了更低学习率。
  2. cls模型官方文档看到是只支持了0和180度的分类,所以倾斜没什么用,除非我自己训练一个。
  3. ppocr_v3我尝试过,没试过蒸馏,但是效果不理想,精度无法满足,这也是我用SVTR_Large的原因

train.log 太大了,无法上传。。所以这个波动是正常的是吗?可能单卡训练这个模型比较困难?

0

@vance-coder 1,余弦学习策略是学习率先增大后减小,目的是防止学习率太小陷入局部最优,因此前几轮的波动会大一些,paddleocr支持可视化训练,建议根据可视化的效果针对性的对模型进行调整。 2,cls模型应当是支持多角度的矫正的,我记得我在技术报告上看到过相关描述; 3,场景文字识别的通用模型要训练到高精度,单纯的从rec入手是远远不够的,应当综合考虑到定位,矫正,识别,这方面建议通过相关论文入手。 4,ppocr_v3 的 rec 是轻量级的模型,主干网络较小,但是常规的识别还是能撑得住的,因此,我认为问题不在于识别模型的精度,而是在其他的处理部分,如果说对性能有一定要求,且应用场景比较常规,可以尝试通过一些图形学操作进行预处理图片,识别率会提升很多。 5,可以尝试适当调整模型大小,增加模型复杂度进行训练

8

好的谢谢,那我得训练集有问题嘛?另外如果我要支持手写识别,是直接加入手写训练集还是额外加入 训练一个手写模型然后加入一个分类器比较好?

9

1,不知道你用的是哪个训练集 2,手写识别不建议使用paddle已有模型,我试了几个模型都达不到较高的精度,中文手写序列化识别模型暂时没有找到精度到90的,正在尝试使用一些比较新的模型,比如pagenet,感觉手写中文还是要用分割+语义模型才能有更好的效果,交流学习可以加我联系方式,因为我也还在探索

3

1,不知道你用的是哪个训练集 2,手写识别不建议使用paddle已有模型,我试了几个模型都达不到较高的精度,中文手写序列化识别模型暂时没有找到精度到90的,正在尝试使用一些比较新的模型,比如pagenet,感觉手写中文还是要用分割+语义模型才能有更好的效果,交流学习可以加我联系方式,因为我也还在探索

训练集是我自己生成了一半,另外一半是网上收集的,pagenet是不是end to end的?训练集不好弄 我的QQ:937316808,很高兴能一起交流

4

我有几个经验之谈:

  • 增大你的 lr,具体数值可以参考 configs 里面的数值;
  • 使用 warmup,具体数值同样参考 configs 里面的配置,文档里也有相关的说明;
  • 统计你 rec 图片的长宽比,找到一个符合你业务场景的图片长宽数值,而不是死板地使用 [32, 320];
  • 如果 training data 的长度差异比较显著,比如有很多单字图片也有很多长字符串图片,考虑使用 padding 方法;
  • 考虑增大 embedding dimension,根据我的众多实验,在没有结果的时候,对 mixer 的增强不如增大 embedding dimension;
  • 考虑清洗你的数据集。
5

我有几个经验之谈:

  • 增大你的 lr,具体数值可以参考 configs 里面的数值;
  • 使用 warmup,具体数值同样参考 configs 里面的配置,文档里也有相关的说明;
  • 统计你 rec 图片的长宽比,找到一个符合你业务场景的图片长宽数值,而不是死板地使用 [32, 320];
  • 如果 training data 的长度差异比较显著,比如有很多单字图片也有很多长字符串图片,考虑使用 padding 方法;
  • 考虑增大 embedding dimension,根据我的众多实验,在没有结果的时候,对 mixer 的增强不如增大 embedding dimension;
  • 考虑清洗你的数据集。

这是很好的建议,非常感谢,我尝试了使用padding,然后得到了一个不错的模型,但是遇到了另外一个问题就是使用PaddleOCR加载inference模型(非命令行方式)的时候,似乎不支持padding,起码我是没看到有padding的参数?

Namespace(alpha=1.0 benchmark=False beta=1.0 cls_batch_num=6 cls_image_shape='3 48 192' cls_model_dir='' cls_thresh=0.9 cpu_threads=10 crop_res_save_dir='' det=True det_algorithm='DB' det_db_box_thresh=0.6 det_db_score_mode='fast' det_db_thresh=0.3 det_db_unclip_ratio=1.5 det_east_cover_thresh=0.1 det_east_nms_thresh=0.2 det_east_score_thresh=0.8 det_fce_box_type='poly' det_limit_side_len=960 det_limit_type='max' det_model_dir='' det_pse_box_thresh=0.85 det_pse_box_type='quad' det_pse_min_area=16 det_pse_scale=1 det_pse_thresh=0 det_sast_nms_thresh=0.2 det_sast_polygon=False det_sast_score_thresh=0.5 draw_img_save_dir='./inference_results' drop_score=0.5 e2e_algorithm='PGNet' e2e_char_dict_path='./ppocr/utils/ic15_dict.txt' e2e_limit_side_len=768 e2e_limit_type='max' e2e_model_dir=None e2e_pgnet_mode='fast' e2e_pgnet_score_thresh=0.5 e2e_pgnet_valid_set='totaltext' enable_mkldnn=False fourier_degree=5 gpu_mem=500 help='==SUPPRESS==' image_dir=None image_orientation=False ir_optim=True kie_algorithm='LayoutXLM' label_list=['0' '180'] lang='ch' layout=True layout_dict_path=None layout_model_dir=None layout_nms_threshold=0.5 layout_score_threshold=0.5 max_batch_size=10 max_text_length=25 merge_no_span_structure=True min_subgraph_size=15 mode='structure' ocr=True ocr_order_method=None ocr_version='PP-OCRv3' output='./output' precision='fp32' process_id=0 rec=True rec_algorithm='SVTR_LCNet' rec_batch_num=6 rec_char_dict_path='' rec_image_shape='3 48 320' rec_model_dir='' recovery=False save_crop_res=False save_log_path='./log_output/' save_pdf=False scales=[8 16 32] ser_dict_path='../train_data/XFUND/class_list_xfun.txt' ser_model_dir=None show_log=True sr_batch_num=1 sr_image_shape='3 32 128' sr_model_dir=None structure_version='PP-Structurev2' table=True table_algorithm='TableAttn' table_char_dict_path=None table_max_len=488 table_model_dir=None total_process_num=1 type='ocr' use_angle_cls=False use_dilation=False use_gpu=True use_mp=False use_onnx=False use_pdserving=False use_space_char=True use_tensorrt=False use_xpu=False vis_font_path='./doc/fonts/simfang.ttf' warmup=False)

0

没试过在 python 里面跑。一般来说,我一般都是用命令行跑的,如果你用 python 跑的话,你可以看一下源代码,把 padding 那一步一直改成 true 就好了。我记得是在 resize 函数里进行修改。

5

@vance-coder 方便加下QQ嘛,我使用的也是SVTR-Large,想跟您交流一下,您看方便嘛

0

进行hard case微调?lr为设置多少?

9

我有几个经验之谈:

  • 增大你的 lr,具体数值可以参考 configs 里面的数值;
  • 使用 warmup,具体数值同样参考 configs 里面的配置,文档里也有相关的说明;
  • 统计你 rec 图片的长宽比,找到一个符合你业务场景的图片长宽数值,而不是死板地使用 [32, 320];
  • 如果 training data 的长度差异比较显著,比如有很多单字图片也有很多长字符串图片,考虑使用 padding 方法;
  • 考虑增大 embedding dimension,根据我的众多实验,在没有结果的时候,对 mixer 的增强不如增大 embedding dimension;
  • 考虑清洗你的数据集。

进行hard case微调?lr为设置多少?