PaddleOCR训练自定义模型避坑指南:从数据标注到推理部署全流程解析
PaddleOCR实战进阶:从数据标注到推理部署的深度避坑指南
如果你已经用PaddleOCR跑过几个demo,觉得这工具确实不错,准备在自己的业务场景里真正用起来,那接下来要面对的可能就是一系列让人头疼的问题了。我自己在几个工业质检和票据处理项目里,从数据准备到模型部署,几乎把能踩的坑都踩了一遍。这篇文章就是把这些经验整理出来,帮你绕过那些常见的陷阱,让自定义模型训练这条路走得更顺畅些。
我们得先明确一个概念:PaddleOCR的通用模型很强,但“通用”意味着它在某些特定场景下会表现得不够理想。比如工业设备上的铭牌文字、医疗单据的手写体、或者某些特殊字体的印刷品,这些都需要针对性的微调。整个过程看似线性——准备数据、标注、训练、部署——但每个环节都有不少细节需要注意,稍不留神就会浪费大量时间。
1. 环境配置:从源头避免兼容性问题
环境问题大概是新手遇到的第一道坎。很多人照着教程安装,结果运行时报各种奇怪的错误,根本原因往往是版本不匹配。PaddleOCR的生态更新很快,但不同组件之间的版本依赖有时候挺微妙的。
1.1 Python环境与依赖管理
我强烈建议使用Anaconda或Miniconda来管理环境,这能最大程度避免系统Python环境被污染。创建环境时,Python版本的选择很关键:
# 创建新的conda环境,建议使用Python 3.8或3.9
conda create -n paddle_ocr python=3.8
conda activate paddle_ocr
为什么是3.8或3.9?因为PaddlePaddle框架对这两个版本的兼容性测试最充分。虽然3.10、3.11也能用,但可能会遇到一些第三方库的兼容性问题,特别是那些还没及时更新的C扩展库。
安装PaddlePaddle时,一定要根据你的硬件情况选择正确的版本:
# CPU版本
pip install paddlepaddle==2.6.0 -i https://mirror.baidu.com/pypi/simple
# GPU版本(CUDA 11.2)
pip install paddlepaddle-gpu==2.6.0.post112 -i https://mirror.baidu.com/pypi/simple
这里有个细节:PaddlePaddle的版本号后面的post112表示CUDA 11.2。如果你用的是其他CUDA版本,比如10.2或11.6,需要对应修改。安装完成后,可以用下面这段代码验证是否安装成功:
import paddle
print(paddle.__version__)
print(paddle.utils.run_check())
如果看到“PaddlePaddle is installed successfully!”就说明基础框架没问题了。
1.2 PaddleOCR源码与依赖安装
接下来是PaddleOCR本身。我建议直接从GitHub克隆最新代码,而不是用pip安装预编译包,因为训练时需要修改配置文件,源码方式更灵活:
git clone https://github.com/PaddlePaddle/PaddleOCR.git
cd PaddleOCR
pip install -r requirements.txt -i https://mirror.baidu.com/pypi/simple
安装依赖时经常遇到的两个问题:
- 网络超时:国内用户可以使用清华、阿里云或百度的镜像源
- 版本冲突:有些教程里requirements.txt的版本可能已经过时
如果遇到某个包安装失败,可以尝试单独安装并指定版本。比如我最近遇到的一个案例是opencv-python版本问题:
# 如果requirements.txt里的opencv-python安装失败
pip install opencv-python==4.8.1.78
pip install opencv-contrib-python==4.8.1.78
注意:有些依赖项在Windows和Linux下的表现可能不同。比如
pycocotools在Windows上需要额外步骤,而Linux下直接pip install就能用。
1.3 验证环境是否可用
环境装好后别急着开始训练,先跑个简单的测试确保一切正常。PaddleOCR提供了预训练模型,我们可以用它们做个快速验证:
from paddleocr import PaddleOCR
# 初始化OCR,第一次运行会自动下载模型
ocr = PaddleOCR(use_angle_cls=True, lang='ch')
# 测试图片识别
img_path = 'doc/imgs/11.jpg' # PaddleOCR自带的示例图片
result = ocr.ocr(img_path, cls=True)
for line in result:
print(line)
如果这段代码能正常运行并输出识别结果,说明环境配置基本正确。如果报错,常见的几个原因和解决方法:
| 错误类型 | 可能原因 | 解决方案 |
|---|---|---|
ModuleNotFoundError | 依赖包缺失 | 检查requirements.txt是否全部安装 |
CUDA error | GPU驱动或CUDA版本不匹配 | 确认CUDA版本与paddlepaddle-gpu版本对应 |
MemoryError | 显存不足 | 减小batch_size或使用CPU版本 |
DownloadError | 模型下载失败 | 手动下载模型放到对应目录 |
2. 数据准备与标注:质量决定模型上限
数据是模型训练的基础,也是很多人最容易忽视的环节。我见过不少项目,模型调参花了大量时间,最后发现问题是出在数据质量上。
2.1 数据采集的实用建议
采集训练数据时,有几个原则需要记住:
- 多样性覆盖:尽可能覆盖实际场景中可能出现的所有情况。比如光照变化(强光、背光、阴影)、拍摄角度(倾斜、透视)、背景复杂度等
- 数量与质量的平衡:对于大多数垂类场景,500-1000张高质量标注图片往往比5000张低质量图片效果更好
- 负样本的重要性:不要只收集有文字的图片,适当加入一些没有文字但背景复杂的图片,帮助模型学习什么是“非文本区域”
在实际项目中,我通常这样规划数据采集:
# 模拟数据采集的类别分布
data_distribution = {
'清晰正面': 30, # 基础样本
'轻度模糊': 20, # 模拟对焦不准
'光照不均': 15, # 部分过曝或欠曝
'倾斜透视': 15, # 非正面拍摄
'复杂背景': 10, # 文字与背景对比度低
'特殊字体': 5, # 项目特有的字体样式
'无文本': 5 # 负样本
}
2.2 PPOCRLabel标注工具的高效使用
PaddleOCR自带的PPOCRLabel是个半自动标注工具,用好了能极大提升效率。但新手经常遇到各种问题,这里分享几个实用技巧。
启动与配置:
cd PaddleOCR/PPOCRLabel
python PPOCRLabel.py --lang ch
如果启动时报错,常见的原因和解决方式:
- PyQt5相关错误:重新安装指定版本
pip install PyQt5==5.15.9 - 缺少动态库:Linux下可能需要安装
libgl1-mesa-glx - 自动标注模型下载失败:可以手动下载模型放到
~/.paddleocr/目录
标注工作流优化:
我习惯的标注流程是这样的:
- 先批量自动标注一批图片
- 按D键快速浏览,只修正明显错误
- 对困难样本(模糊、小文字、特殊字体)重点标注
- 定期保存,避免意外关闭丢失进度
提示:标注时尽量保证矩形框紧贴文字边缘,但不要切到文字本身。对于弯曲文本,PPOCRLabel也支持四点标注,按住Ctrl键可以调整单个点的位置。
标注数据的管理:
标注完成后会生成几个关键文件,它们的用途需要清楚:
Label.txt:检测模型训练标签,格式为图片路径\t[{"transcription": "文字", "points": [[x1,y1],...]}, ...]rec_gt.txt:识别模型训练标签,格式为图片路径\t文字crop_img/:自动裁剪出的文字区域图片fileState.txt:记录哪些图片已经标注完成
2.3 数据集划分与格式转换
PPOCRLabel提供了自动划分数据集的脚本,但有时候我们需要更精细的控制:
# 基本用法
python gen_ocr_train_val_test.py --datasetRootPath ../train_data/my_data
# 自定义划分比例
python gen_ocr_train_val_test.py --datasetRootPath ../train_data/my_data --trainValTestRatio 7:2:1
# 指定输出目录
python gen_ocr_train_val_test.py --datasetRootPath ../train_data/my_data --outputPath ../custom_data
这里有个容易踩坑的地方:文件路径中的中文和空格。虽然现在大部分情况下能处理,但为了保险起见,建议:
- 使用英文命名文件夹和文件
- 避免特殊字符和空格
- 使用相对路径而不是绝对路径
数据集划分后,目录结构应该是这样的:
train_data/
├── det/
│ ├── train/
│ ├── val/
│ ├── test/
│ ├── train.txt
│ ├── val.txt
│ └── test.txt
└── rec/
├── train/
├── val/
├── test/
├── train.txt
├── val.txt
└── test.txt
3. 模型训练:参数调优与监控
数据准备好了,接下来就是训练模型。这个阶段最容易出现的问题就是训练了半天,效果却不理想,或者干脆不收敛。
3.1 配置文件深度解析
PaddleOCR使用YAML配置文件管理所有训练参数。新手常犯的错误是直接修改官方配置文件,然后发现各种报错。正确做法是复制一份再修改:
cp configs/det/ch_ppocr_v2.0/ch_det_res18_db_v2.0.yml configs/det/my_det_config.yml
需要重点关注的配置项:
Global部分:
Global:
use_gpu: true
epoch_num: 1200
log_smooth_window: 20
print_batch_step: 10
save_model_dir: ./output/my_det_model/
save_epoch_step: 200
eval_batch_step: [0, 100] # 从第0个batch开始,每100个batch评估一次
pretrained_model: ./pretrain_models/ch_ppocr_mobile_v2.0_det_train/best_accuracy
checkpoints: # 用于恢复训练
save_inference_dir: ./inference_model/my_det/
Train部分:
Train:
dataset:
name: SimpleDataSet
data_dir: ./train_data/det/train/ # 训练图片目录
label_file_list:
- ./train_data/det/train.txt # 训练标签文件
transforms:
- DecodeImage: # 图片解码
img_mode: BGR
channel_first: false
- DetLabelEncode: # 标签编码
- IaaAugment: # 数据增强
augmenter_args:
- type: Fliplr
args:
p: 0.5
- type: Affine
args:
rotate: [-10, 10]
translate_percent:
x: [-0.05, 0.05]
y: [-0.05, 0.05]
scale: [0.95, 1.05]
shear: [-5, 5]
- EastRandomCropData: # 随机裁剪
- MakeBorderMap: # 生成边界图
- MakeShrinkMap: # 生成收缩图
- NormalizeImage: # 归一化
scale: 1./255.
mean: [0.485, 0.456, 0.406]
std: [0.229, 0.224, 0.225]
order: 'hwc'
- ToCHWImage: # 转换通道顺序
- KeepKeys: # 保留的键
keep_keys: ['image', 'threshold_map', 'threshold_mask', 'shrink_map', 'shrink_mask']
loader:
shuffle: true
batch_size_per_card: 8 # 每张GPU的batch size
drop_last: true
num_workers: 4 # 数据加载线程数
关键参数的经验值:
| 参数 | 建议值 | 说明 |
|---|---|---|
batch_size_per_card | 8-16 | 根据显存调整,2的倍数 |
num_workers | CPU核心数的一半 | 太多反而可能降低效率 |
epoch_num | 500-1200 | 小数据集需要更多epoch |
learning_rate | 0.001 | 可从0.001开始,观察loss变化 |
warmup_epoch | 5 | 学习率预热轮数 |
3.2 训练过程监控与调试
开始训练的命令很简单:
python tools/train.py -c configs/det/my_det_config.yml
但训练开始后,如何判断模型是否在正常学习?我主要看这几个指标:
- Loss曲线:应该在前几个epoch快速下降,然后缓慢下降并趋于平稳
- 学习率变化:如果使用了warmup,学习率会从0逐渐增加到设定值
- 评估指标:每轮评估的准确率应该逐步提升
如果遇到问题,可以按这个思路排查:
问题:Loss不下降或波动很大
- 可能原因:学习率太大
- 解决方案:减小学习率,比如从0.001降到0.0001
- 检查命令:
python tools/train.py -c configs/det/my_det_config.yml -o Optimizer.lr.learning_rate=0.0001
问题:训练很慢
- 可能原因:数据加载瓶颈或GPU利用率低
- 解决方案:增加
num_workers,使用更快的存储,检查GPU监控 - 检查命令:
watch -n 1 nvidia-smi# Linux下监控GPU使用率
问题:显存不足
- 可能原因:batch_size太大或图片尺寸太大
- 解决方案:减小batch_size,调整图片resize参数
- 修改配置:
batch_size_per_card: 4和limit_side_len: 960
3.3 识别模型训练的特殊考虑
文字识别模型的训练有些特殊之处。除了检测模型需要的配置外,还需要注意:
字典文件配置:
Global:
character_dict_path: ppocr/utils/ppocr_keys_v1.txt # 中英文字典
# 或者使用自定义字典
# character_dict_path: ./train_data/rec/my_dict.txt
character_type: ch # 语言类型:ch、en、chinese_cht、japan等
max_text_length: 25 # 最大文本长度,根据实际数据调整
自定义字典的创建: 如果你的场景有特殊字符(比如数学符号、特殊单位、行业术语),需要创建自定义字典:
# 生成自定义字典文件
special_chars = set()
with open('train_data/rec/train.txt', 'r', encoding='utf-8') as f:
for line in f:
_, text = line.strip().split('\t')
special_chars.update(text)
# 写入字典文件
with open('train_data/rec/my_dict.txt', 'w', encoding='utf-8') as f:
for char in sorted(special_chars):
f.write(char + '\n')
识别模型常见问题:
注意:识别模型训练初期,准确率(acc)为0是正常的,因为模型还在学习字符特征。通常训练几十个epoch后acc才会开始上升。如果训练几百个epoch后acc还是0,那可能是数据或配置有问题。
另一个常见问题是过拟合:训练集准确率很高(比如95%),但验证集准确率很低(比如70%)。这时候可以:
- 增加数据增强的强度
- 添加或增大L2正则化
- 使用早停(early stopping)
4. 模型评估与优化策略
训练完成后,不能只看最后的准确率数字,还需要深入分析模型的表现,找出可以改进的地方。
4.1 多维度评估模型性能
PaddleOCR提供了多种评估工具,我通常按这个顺序进行:
基础评估:
# 检测模型评估
python tools/eval.py -c configs/det/my_det_config.yml -o Global.checkpoints=./output/my_det_model/best_accuracy
# 识别模型评估
python tools/eval.py -c configs/rec/my_rec_config.yml -o Global.checkpoints=./output/my_rec_model/best_accuracy
评估结果会显示精确率(Precision)、召回率(Recall)和F1值。但只看这些整体指标还不够,需要进一步分析:
错误分析:
# 分析检测模型的常见错误类型
error_cases = {
'漏检': [], # 该检出的文字没检出
'误检': [], # 把非文字区域检出为文字
'框不准': [], # 检测框与文字不匹配
'合并错误': [] # 多个文字行被合并成一个框
}
# 分析识别模型的错误
rec_errors = {
'形近字错误': [], # 如'未'和'末'
'生僻字错误': [], # 字典中缺少的字
'长度错误': [], # 识别出的字符数不对
'完全错误': [] # 识别结果与真实值完全不同
}
在实际项目中,我通常会抽样检查错误样本,手动分析原因。比如发现很多"漏检"发生在小文字上,那可能需要:
- 增加小文字的训练样本
- 调整检测模型的最小检测尺寸
- 在预处理时尝试不同的resize策略
4.2 模型融合与集成技巧
单个模型可能在某些场景表现不佳,这时候可以考虑模型集成。PaddleOCR支持多种集成方式:
多模型投票:
from paddleocr import PaddleOCR
# 初始化多个模型(可以是不同结构或不同训练数据的模型)
ocr1 = PaddleOCR(det_model_dir='./model/det_v1/', rec_model_dir='./model/rec_v1/')
ocr2 = PaddleOCR(det_model_dir='./model/det_v2/', rec_model_dir='./model/rec_v2/')
ocr3 = PaddleOCR(det_model_dir='./model/det_v3/', rec_model_dir='./model/rec_v3/')
def ensemble_ocr(img_path):
results = []
for ocr in [ocr1, ocr2, ocr3]:
result = ocr.ocr(img_path, cls=True)
results.append(result)
# 简单的投票策略:取三个模型都识别出的结果
final_result = []
for i in range(min(len(r) for r in results)):
texts = [r[i][1][0] for r in results if i < len(r)]
# 如果至少两个模型结果一致,则采用
from collections import Counter
counter = Counter(texts)
if counter.most_common(1)[0][1] >= 2:
final_result.append(results[0][i])
return final_result
模型蒸馏: 对于资源受限的场景,可以使用知识蒸馏将大模型的知识迁移到小模型:
# 使用大模型(教师模型)指导小模型(学生模型)训练
python tools/train.py -c configs/det/ch_ppocr_v2.0/ch_det_res18_db_v2.0.yml \
-o Global.pretrained_model=./pretrain_models/ch_ppocr_server_v2.0_det_train/best_accuracy \
Architecture.Models.Student.pretrained=./pretrain_models/ch_ppocr_mobile_v2.0_det_train/best_accuracy
4.3 推理优化与加速
训练好的模型最终要部署使用,推理速度往往很关键。PaddleOCR提供了多种优化手段:
模型量化:
# 将FP32模型量化为INT8,大幅减小模型体积并提升推理速度
python tools/export_model.py -c configs/det/my_det_config.yml \
-o Global.pretrained_model=./output/my_det_model/best_accuracy \
Global.save_inference_dir=./inference_model/my_det_int8 \
Global.quantization=True
量化后的模型精度可能会有轻微下降(通常1-2%),但推理速度可以提升2-3倍,模型体积减少到原来的1/4。
多线程推理:
from paddleocr import PaddleOCR
import concurrent.futures
ocr = PaddleOCR(use_angle_cls=True)
def process_image(img_path):
return ocr.ocr(img_path, cls=True)
# 批量处理图片
image_paths = ['img1.jpg', 'img2.jpg', 'img3.jpg', 'img4.jpg']
with concurrent.futures.ThreadPoolExecutor(max_workers=4) as executor:
results = list(executor.map(process_image, image_paths))
GPU推理优化:
# 启用TensorRT加速(需要额外安装TensorRT)
ocr = PaddleOCR(
use_angle_cls=True,
use_tensorrt=True,
precision='fp16', # 使用半精度浮点数
device='gpu'
)
5. 部署实践:从开发环境到生产系统
模型训练好了,评估结果也不错,接下来就是部署到实际环境中。这个阶段会遇到很多训练时没有的问题。
5.1 模型转换与封装
训练保存的是训练模型(包含优化器状态等),部署需要的是推理模型:
# 转换检测模型
python tools/export_model.py -c configs/det/my_det_config.yml \
-o Global.pretrained_model=./output/my_det_model/best_accuracy \
Global.save_inference_dir=./inference_model/det_infer
# 转换识别模型
python tools/export_model.py -c configs/rec/my_rec_config.yml \
-o Global.pretrained_model=./output/my_rec_model/best_accuracy \
Global.save_inference_dir=./inference_model/rec_infer
转换后的推理模型包含三个文件:
model.pdmodel:模型结构model.pdiparams:模型参数model.pdiparams.info:模型信息
模型封装: 为了方便调用,我通常会写一个封装类:
import os
import cv2
import numpy as np
from paddleocr import PaddleOCR
class CustomOCR:
def __init__(self, det_model_dir, rec_model_dir, use_gpu=True):
self.ocr = PaddleOCR(
det_model_dir=det_model_dir,
rec_model_dir=rec_model_dir,
cls_model_dir='ch_ppocr_mobile_v2.0_cls_infer/', # 方向分类模型
use_angle_cls=True,
lang='ch',
use_gpu=use_gpu,
gpu_mem=500, # GPU内存限制(MB)
max_text_length=50,
det_db_thresh=0.3,
det_db_box_thresh=0.5,
det_db_unclip_ratio=1.6,
use_dilation=False,
det_db_score_mode='fast',
drop_score=0.5
)
def process_image(self, img_path):
"""处理单张图片"""
result = self.ocr.ocr(img_path, cls=True)
return self._format_result(result)
def process_batch(self, img_paths, batch_size=4):
"""批量处理图片"""
results = []
for i in range(0, len(img_paths), batch_size):
batch = img_paths[i:i+batch_size]
for img_path in batch:
result = self.process_image(img_path)
results.append(result)
return results
def _format_result(self, result):
"""格式化识别结果"""
if result is None:
return []
formatted = []
for line in result:
if line: # 可能为空
for word_info in line:
points = word_info[0]
text = word_info[1][0]
confidence = word_info[1][1]
formatted.append({
'text': text,
'confidence': float(confidence),
'bbox': points
})
return formatted
def draw_result(self, img_path, result, save_path=None):
"""在图片上绘制识别结果"""
img = cv2.imread(img_path)
for item in result:
points = np.array(item['bbox'], dtype=np.int32)
# 绘制边界框
cv2.polylines(img, [points], True, (0, 255, 0), 2)
# 添加文字
cv2.putText(img, item['text'], tuple(points[0]),
cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255), 1)
if save_path:
cv2.imwrite(save_path, img)
return img
5.2 服务化部署方案
对于生产环境,通常需要将OCR能力封装成服务。PaddleOCR官方提供了多种部署方案:
基于PaddleServing的部署:
# 安装PaddleServing
pip install paddle-serving-server-gpu==0.9.0
pip install paddle-serving-app==0.9.0
pip install paddle-serving-client==0.9.0
# 转换模型为Serving格式
python -m paddle_serving_client.convert \
--dirname ./inference_model/det_infer \
--model_filename model.pdmodel \
--params_filename model.pdiparams \
--serving_server ./serving_server/det \
--serving_client ./serving_client/det
编写服务端代码:
from paddle_serving_server.web_service import WebService
import numpy as np
class OCRService(WebService):
def preprocess(self, feed=[], fetch=[]):
# 预处理请求数据
img_data = feed[0]['image']
img = cv2.imdecode(np.frombuffer(img_data, np.uint8), cv2.IMREAD_COLOR)
# 这里添加你的预处理逻辑
return feed, fetch
def postprocess(self, feed=[], fetch=[], fetch_map=None):
# 后处理识别结果
result = fetch_map['output']
# 格式化输出
return {'result': result}
ocr_service = OCRService(name="ocr")
ocr_service.load_model_config("serving_server")
ocr_service.prepare_server(workdir="workdir", port=9292)
ocr_service.run_server()
Docker容器化部署:
FROM paddlepaddle/paddle:2.6.0-gpu-cuda11.2-cudnn8
# 安装依赖
RUN pip install paddleocr paddlepaddle-gpu==2.6.0 -i https://mirror.baidu.com/pypi/simple
# 复制模型文件
COPY inference_model /app/inference_model
COPY serving_server /app/serving_server
# 复制代码
COPY ocr_service.py /app/
# 暴露端口
EXPOSE 9292
# 启动服务
CMD ["python", "/app/ocr_service.py"]
5.3 性能监控与维护
模型部署后,还需要持续监控和维护:
性能监控指标:
class OCRMonitor:
def __init__(self):
self.metrics = {
'total_requests': 0,
'successful_requests': 0,
'avg_processing_time': 0,
'error_types': {},
'confidence_distribution': []
}
def record_request(self, processing_time, success=True, error_type=None):
self.metrics['total_requests'] += 1
if success:
self.metrics['successful_requests'] += 1
else:
self.metrics['error_types'][error_type] = \
self.metrics['error_types'].get(error_type, 0) + 1
# 更新平均处理时间
old_avg = self.metrics['avg_processing_time']
old_count = self.metrics['total_requests'] - 1
self.metrics['avg_processing_time'] = \
(old_avg * old_count + processing_time) / self.metrics['total_requests']
def record_confidence(self, confidence):
self.metrics['confidence_distribution'].append(confidence)
# 只保留最近1000个记录
if len(self.metrics['confidence_distribution']) > 1000:
self.metrics['confidence_distribution'].pop(0)
def get_health_report(self):
success_rate = (self.metrics['successful_requests'] /
max(self.metrics['total_requests'], 1))
report = {
'success_rate': success_rate,
'avg_processing_time_ms': self.metrics['avg_processing_time'] * 1000,
'total_requests': self.metrics['total_requests'],
'error_distribution': self.metrics['error_types']
}
if self.metrics['confidence_distribution']:
confidences = self.metrics['confidence_distribution']
report['avg_confidence'] = sum(confidences) / len(confidences)
report['low_confidence_rate'] = \
len([c for c in confidences if c < 0.7]) / len(confidences)
return report
模型更新策略:
生产环境的模型不能随意更新,需要有完善的流程:
- A/B测试:新模型与旧模型并行运行,对比效果
- 灰度发布:先在小流量上测试,逐步扩大范围
- 回滚机制:如果新模型出现问题,能快速回退到旧版本
- 数据收集:收集线上数据,用于下一轮模型优化
class ModelUpdater:
def __init__(self, model_dir):
self.model_dir = model_dir
self.current_model = None
self.new_model = None
self.load_current_model()
def load_current_model(self):
# 加载当前生产模型
self.current_model = CustomOCR(
det_model_dir=f'{self.model_dir}/current/det',
rec_model_dir=f'{self.model_dir}/current/rec'
)
def deploy_new_model(self, new_model_path):
# 部署新模型
self.new_model = CustomOCR(
det_model_dir=f'{new_model_path}/det',
rec_model_dir=f'{new_model_path}/rec'
)
# 开始A/B测试
return self.start_ab_test()
def start_ab_test(self, traffic_split=0.1):
"""A/B测试,10%流量走新模型"""
import random
def select_model():
if random.random() < traffic_split:
return self.new_model
return self.current_model
return select_model
实际部署中,我还遇到过一些特定场景的问题。比如在嵌入式设备上,内存和计算资源有限,这时候需要更激进的优化:使用更小的模型结构、更低的精度(比如INT8量化)、甚至裁剪掉一些不常用的功能。而在高并发服务器上,可能需要考虑模型的多实例加载、请求队列管理、异步处理等。
每个项目的情况都不一样,关键是理解整个流程中的关键节点,知道在哪里可能出问题,以及出了问题怎么排查。PaddleOCR的文档和社区都很活跃,遇到解决不了的问题,去GitHub上搜一下issue,很可能已经有人遇到过类似的问题并给出了解决方案。
更多推荐
所有评论(0)