入职一月内为公司解决当前面临的两大难题,获得公司CEO表彰 ~
.jpg)
以下为 7 月份版本,后续又进行了更多迭代和优化
PaddleOCR
项目背景
我们遇到的主要问题是PaddleOCR在昇腾服务器上推理速度显著偏慢,无法满足生产需求,而且由于Paddle框架本身和昇腾的兼容性问题,一直没有好的解决方案。了解到可以用Pytorch来推理PaddleOCR的模型,而且能达到比较好的性能效果。
虽然开源社区有”PaddleOCR2PyTorch”这个项目,但它只是提供了基础的模型转换,缺少完整的pipeline和服务化能力,最关键的是没有适配昇腾NPU。所以决定在这个基础上做深度开发和优化。
技术实现和突破
第一步是解决NPU适配问题。 修改源代码,让模型加载时能够自动从CPU转向NPU,同时配置了输入数据流也能转入NPU卡进行处理。
第二步是整合完整的推理流程。 OCR涉及到Det(检测)、Cls(方向分类)、Rec(识别)三个模型,基于原有的推理代码编写了上层Pipeline,将三个模型的交互和最终输出进行整合,然后开发基于FastAPI的服务化层代码。这样就有了一个完整的、可以直接部署使用的OCR服务。
第三步是性能优化。 经过前面两步,模型已经能在NPU上成功运行并提供服务,单页处理时间达到了1.5秒。但发现还有很大的优化空间,因为PaddleOCR推理时会先用检测模型把一张图片按照文本区域切分成数十张小图,而分类和识别模型其实是支持批处理的。所以可以通过组batch的方式,进一步提升显存利用率和处理性能,最终把单页处理时间优化到了0.5-0.8秒。具体来说,分类模型用24图批处理,识别模型用12图批处理。
第四步是扩展到多图批处理。 前面优化的是单张图片内部的批处理,进一步在服务层提供了多图批处理接口,这样在处理多张图片时能够进一步优化性能,最快可达0.2-0.3s一页,充分发挥NPU的计算能力。
专项技术攻关
在医疗检验报告中需要识别检验项的箭头等异常符号,后于后续AE判断。但是默认参数识别不出来,经过多次尝试和调优,找到了一个合适的参数组合:把det_limit_type从max改为min来避免小箭头在长边缩放时丢失,把det_db_thresh降低到0.12来捕捉箭头边缘的弱信号,调整det_db_box_thresh到0.15避免漏检低对比度的箭头,设置det_db_unclip_ratio为1.8确保箭头的完整性,启用use_dilation来增强细小箭头的连通性。
1 | det_limit_type: 'min' # 避免小目标在长边缩放时丢失 |
另外一个是大像素图片的处理。我们发现对于大像素图片会出现识别为空或者显存过高的现象,原因是det_limit_type设置为min会导致大像素图片进一步扩大,从而丢失细节或者显存超标,但如果改为max虽然可以识别大像素图片,却会导致箭头识别不到。我们的解决方案是实现了按需渐进式缩放策略:对于识别失败的图片,系统会自动进行多轮缩放尝试,分别是15%、25%、35%的缩放比例,每次缩放后都重新识别,这样既保证了对大像素图片的处理能力,又不会影响小目标的识别效果。
通过这一系列的问题,基本达到了生产可用的标准。性能方面,单页处理时间从最初的5秒+到1.5秒,最终优化到了0.5-0.8秒,切换推理框架以及使用批处理相比之前获得了多倍的性能提升,充分利用昇腾NPU的算力。功能方面,解决了基础的OCR识别问题,也针对医疗检验报告等专业场景做了优化,特别是箭头符号的识别准确率有了显著提升。后续仍需在实际场景中进行检验,并根据badcase持续优化。
HIPAA医疗数据脱敏
原始方案为华为提供、开发,但存在较大问题,入职后重新开发。
项目背景与挑战
此项目主要是要解决医疗文档中敏感信息的自动识别。最初的技术方案存在明显不足。华为提供的初版方案完全依赖大模型识别,单张图片处理需要60秒以上。提示词设计过于简陋,脱敏覆盖面积过大,经常把不该遮盖的内容也遮住了。大模型在复杂医疗场景下表现不稳定,难以准确理解HIPAA标准的具体要求。
技术优化历程
第一阶段优化:提升精度和性能
第一阶段我们实现了从60秒到12秒的突破,主要从三个维度进行了优化。
首先是精准遮盖。原方案是OCR识别出文本块后,华为直接遮盖整个文本块,这样做既粗糙又影响阅读。通过开发更智能的精准遮盖算法来解决,先分析文本块的边界坐标和尺寸,然后根据中英文字符特点计算每个字符的平均宽度,其中中文字符被赋予1.8倍权重来适应中英文混合文本。对于每个匹配的关键词,根据其在文本块中的前缀宽度和自身宽度,精确推算敏感词在图片上的坐标位置,实现精准遮盖。
其次是提示词工程优化。我们重新设计了输出结构,避免无效分类输出,同时优化了提示词逻辑,大幅提升了大模型的理解准确性。
第三是工程化规则增强。针对医疗文档特点,设计了专门的正则表达式规则,大幅提升了身份证、电话号码等标准格式信息的识别精度。
这个阶段的效果是处理时间从60秒降低到12秒,精度也显著提升了。
第二阶段重构:重构架构,性能得到大幅度提升
虽然第一阶段有了改善,但大模型的能力边界和幻觉问题仍然存在,误识别情况时有发生。
经过探索多种技术路线:1.分词模型方案能提升精度,但仍需大模型参与判断,性能瓶颈依然存在;2.分词加词义识别在通用场景表现不错,但在医疗专业场景下错误率较高;3.最终选择了完全重构的方案,采用Presidio PII检测框架,并集成spaCy中文模型。
选择Presidio的原因是它高度可定制,支持自定义识别规则,具备上下文相关检测能力,通过深度定制化开发,可以适合复杂医疗场景。
核心技术架构
基于Presidio的特点,设计了四层识别架构。
第一层是规则识别层,主要处理身份证、电话号码等强模式标识符,使用PatternRecognizer加正则表达式,置信度达到0.95到0.98。
第二层是上下文增强识别层,利用context参数减少误报,采用词典匹配加邻近关键词验证的方式,置信度在0.85到0.95之间。
第三层是spaCy通用实体识别层,主要做人名、地名、机构名的补充识别,使用zh_core_web_trf中文模型,置信度为0.85。
第四层是智能过滤层,由于医疗业务场景的复杂性,仍有医疗名称、学术术语被误识别,那么在最后添加一个过滤层。通过医学术语白名单过滤、上下文感知智能判断和模式匹配优化过滤,大幅度减少误报率。
共配置32个专业识别器和多个过滤器,覆盖了HIPAA要求的敏感信息类型。后续将开发支持自定义配置的脱敏方式,适配各类不同的业务场景。也需要在实际业务场景中持续检验,根据不同的badcase持续优化。
实施效果
性能提升效果非常显著。华为原版单页处理时间60秒,十页需要600秒。我们第一版优化后单页12秒,十页120秒,实现了5倍性能提升。第二版重构后单页1秒,十页5秒,相比原版实现了60倍的性能提升。
| 版本 | 一页时间 | 十页时间 |
|---|---|---|
| 原版 | 60秒 | 600秒 |
| 第一版优化 | 12秒 | 120秒 |
| 第二版重构 | 1秒内 | 5秒 |
其中脱敏核心服务系统,又搭配了一个脱敏平台来使用,也是全部由我来开发:
开发过程:https://www.chongwenz.cn/%E6%8A%80%E6%9C%AF/AI/ai-vibe-coding-01/
效果展示:https://www.chongwenz.cn/%E6%8A%80%E6%9C%AF/AI/ai-vibe-coding-02-tuomin/