尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

字符集优化 + KenLM 语言模型纠错实战

字符集优化 + KenLM 语言模型纠错实战 1. 问题现象好好的“黛墨色”怎么就成了乱码在业务系统中我们经常需要对商品图片、票据、合同等做 OCR 识别。理想情况下图片里的“黛墨色”三个字应该被准确识别出来。但实际运行时OCR 引擎却经常输出一堆乱码比如“黛墨色”被读成“黛?墨?色”或者更离谱的“黛墨色”变成“黛墨色”之外的奇怪字符。这种问题在中文场景下尤其突出。原因在于 OCR 引擎的字符集覆盖范围太广从几千个常用汉字到生僻字、特殊符号、全角半角字符全都包含在内。搜索空间越大模型“乱猜”的概率就越高最终输出的结果就越容易出现乱码。2. 问题根因字符集太宽 缺少语言约束要解决乱码问题先要理解它为什么发生。核心原因有两个第一字符集过宽导致搜索空间爆炸。OCR 识别本质上是一个分类问题模型要从候选字符集中挑出最可能的字符。候选字符集有几千个字符时模型对每个字符的区分难度会显著上升尤其是形近字、生僻字之间更容易混淆。第二缺少语言层面的约束。OCR 模型通常只关注图像特征对“这个词在中文里是否合理”没有感知。比如“文付宝”和“支付宝”在字形上非常接近OCR 模型可能因为图像模糊而误判但语言模型知道“支付宝”才是真实存在的词而“文付宝”几乎不会出现。3. 解决思路识别前收窄 识别后纠错针对上述两个根因我们的解决思路分两步走识别前缩小候选范围通过自定义字符集只保留业务相关的字符把 OCR 搜索空间从几千个字符收窄到几百个从源头减少“乱猜”的概率。识别后加一层语言模型纠错引入 KenLM 语言模型做浅层融合对 OCR 的初步结果进行二次校验把“文付宝”纠正为“支付宝”这类错误拦截下来。整体流程如下输入图片自定义字符集约束OCR 识别KenLM 语言模型纠错输出正确文本4. 第一步自定义字符集收窄搜索空间自定义字符集的核心思路是根据业务场景只保留可能出现的字符。比如做服装电商的 OCR字符集里只需要包含常见颜色词、尺码、品牌名、面料词等完全不需要覆盖全部汉字。# 自定义字符集示例服装行业 OCRbusiness_charsset()# 颜色词business_chars.update(黛墨色藏青月白鹅黄绯红缃色竹青)# 尺码business_chars.update(SMLXLXXL均码)# 常用汉字业务高频字business_chars.update(上衣裤裙装面料棉麻丝毛呢)# 数字和字母business_chars.update(0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ)# 转成 OCR 引擎需要的格式custom_charset.join(sorted(business_chars))print(f自定义字符集大小:{len(custom_charset)})把字符集从几千个收窄到几百个之后OCR 模型的搜索空间大幅缩小识别准确率会明显提升乱码出现的概率也随之下降。5. 第二步KenLM 语言模型浅层融合纠错字符集优化能解决一部分问题但遇到形近字混淆时仍然可能出错。这时就需要 KenLM 语言模型上场。KenLM 是一个高效的语言模型工具包支持训练和加载 n-gram 语言模型。我们可以用业务语料训练一个 KenLM 模型然后对 OCR 的识别结果做浅层融合纠错。5.1 训练 KenLM 模型# 准备业务语料每行一句话# corpus.txt 内容示例# 这件衣服是黛墨色的# 支付宝到账一百元# 面料采用纯棉材质# 使用 KenLM 训练 3-gram 模型lmplz-o3--textcorpus.txt--arpaoutput.arpa# 转换为二进制格式加快加载速度build_binary output.arpa output.binary5.2 加载模型并纠错importkenlm# 加载训练好的语言模型modelkenlm.Model(output.binary)defocr_correct(text,candidates): 对 OCR 结果进行语言模型纠错 text: OCR 初步识别结果 candidates: 每个位置的候选字符列表 best_scorefloat(-inf)best_texttext# 遍历候选组合用语言模型打分forcomboincandidates:candidate_text.join(combo)scoremodel.score(candidate_text,bosTrue,eosTrue)ifscorebest_score:best_scorescore best_textcandidate_textreturnbest_text# 示例OCR 把支付宝识别成文付宝# 候选字符第一个字可能是支或文后两个字固定candidates[[支,付,宝],[文,付,宝],]resultocr_correct(文付宝,candidates)print(f纠错结果:{result})# 输出支付宝语言模型会给“支付宝”打出远高于“文付宝”的分数因为“支付宝”在语料中频繁出现而“文付宝”几乎不存在。这样就能把这类错误有效拦截下来。6. 完整流程整合把两步结合起来就构成了一个完整的 OCR 纠错流水线defocr_pipeline(image_path):# 第一步用自定义字符集做 OCR 识别raw_resultocr_recognize(image_path,charsetcustom_charset)# 第二步生成候选字符组合candidatesgenerate_candidates(raw_result,custom_charset)# 第三步KenLM 语言模型纠错final_resultocr_correct(raw_result,candidates)returnfinal_result6.5 三种方案效果对比为了更直观地看到每一步优化带来的收益这里把「未优化」「仅自定义字符集」「自定义字符集 KenLM」三种方案放在一起对比以下为业务场景下的预期效果实际数值会随语料和图片质量波动方案准确率乱码率耗时未优化约 85%约 8%基准最快仅自定义字符集约 93%约 3%略增字符集收窄搜索更快自定义字符集 KenLM约 97%约 0.5%增加多一次语言模型打分简要说明未优化字符集覆盖几千个字符模型“乱猜”空间大形近字、生僻字容易混淆乱码率最高但因为没有额外处理耗时最短。仅自定义字符集搜索空间从几千个收窄到几百个模型区分难度下降准确率明显提升、乱码率大幅下降字符集变小后单次识别反而更快整体耗时基本持平或略增。自定义字符集 KenLM在字符集优化的基础上再叠加语言模型浅层融合能拦截“文付宝→支付宝”这类形近字错误准确率进一步提升、乱码率降到极低代价是多一次 n-gram 打分耗时有所增加但对生产场景通常可接受。7. 效果与总结通过“识别前缩小候选范围 识别后语言模型纠错”的组合方案我们取得了明显的效果自定义字符集把搜索空间从几千个字符收窄到几百个OCR 基础准确率显著提升乱码率大幅下降。KenLM 语言模型浅层融合有效拦截了“文付宝→支付宝”这类形近字错误。两者结合业务场景下的 OCR 可用性达到了生产标准。这套方案的核心思想是不要指望 OCR 模型一步到位而是通过工程手段在识别前后分别加约束。字符集优化解决“认不准”的问题语言模型解决“认错但像”的问题双管齐下乱码问题就能得到有效控制。
返回列表