ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

《大话文渊慧典》:七

《大话文渊慧典》:七 第七篇后处理的魔法——OCR的最后一公里——大胖老师“前面几讲咱们把PDF拆了把图洗了把版面也分析完了字也认出来了。是不是该收工了”——小菜“那肯定啊字都认出来了剩下的不就是复制粘贴吗”——二黑推了推眼镜把一叠打印纸推到小菜面前“那你看看这个。这是昨天跑完的一本县志原书乾隆年间的。识别出来的字单独看每个都对连起来读——‘已所不欲勿施於人’‘日’和‘曰’随机切换‘玄’字缺一笔变成了乱码双行夹注和正文混在一起中间还插了一段眉批完全不通。这就是你以为的‘复制粘贴’”——小菜翻了翻脸皱成一团“这……这也叫识别完了”——大胖老师端起保温杯慢悠悠地说“识别完只是把矿石挖出来了。后处理才是把矿石炼成铁、打成刀的过程。今天咱们就讲讲从一堆乱七八糟的字符串到一本可搜索、可复制、看着跟原书一样的双层PDF中间到底经历了什么。”一、后处理的第一道工序置信度标注与校对辅助大胖老师在白板上画了一个方框里面写着“置信度”三个字。“OCR对每个字都有一个打分0到1之间。1就是‘我百分百确定是这个字’0就是‘我瞎猜的’。对古籍来说大部分字的置信度在0.9以上但总有那么几个字——模糊的、虫蛀的、异体的——得分很低。传统做法是整篇人工校对一个字一个字地比对王大姐一天只能校二十页校到退休也校不完一个馆。”“我们的思路是只让王大姐看那些模型‘不确定’的字。”二黑调出文渊慧典的校对界面“系统设了一个阈值0.85。置信度低于0.85的字自动标黄高亮。校对人员打开文档所有黄字一目了然其他的默认正确不用看。这一下校对效率提升了至少三倍。”小菜凑近屏幕“那万一把对的标黄了错的没标怎么办”“这就是阈值的艺术。”大胖老师解释“设高了黄字太多累设低了漏网之鱼太多险。0.85是我们用几千页古籍反复测试后找到的平衡点。而且王大姐在实际校对中如果发现黄字是对的点一下‘确认’就消掉了系统会记住这个反馈以后类似情况会调高置信度。时间越长系统越准黄字越少。我们用活的数据让模型和王大姐一起成长。”小菜感慨“这就像老师改卷子只改那些答案写得不清楚的题其他全算对。”二黑面无表情地补了一句“比喻很贴切但我希望下次你交作业的时候不要用这个理论。”二、后处理的第二道工序语言模型自动纠错“置信度标注解决的是‘告诉你在哪儿有问题’但问题本身还没解决。”大胖老师又画了一个方框写上“上下文纠错”。“古籍里最常见的错误不是乱码而是形近字混淆。‘己’和‘已’‘曰’和‘日’‘人’和‘入’‘末’和‘未’。这些字长得像OCR经常犹豫不决。单看字形神仙也难辨但如果看上下文答案往往很清晰。”二黑调出一组实例“比如‘己所不欲勿施於人’。OCR可能把‘己’识别成‘已’置信度0.7。后处理系统会怎么做它把这个句子送进一个古文语言模型——一个用四库全书语料训练过的模型。模型一看‘X所不欲’就知道前面应该是‘己’因为‘己所不欲’是固定搭配它在训练数据里见过几万次‘已所不欲’一次都没见过。于是系统自动把‘已’纠正为‘己’。”“这个语言模型是我们自己微调过的。”大胖老师补充“通用语言模型主要基于现代汉语训练遇到古文会水土不服。我们把《四库全书》《大藏经》这些语料整理出来在BERT-base-Chinese的基础上做古文领域适配训练了一个专用的古文语言模型。它不仅知道‘己所不欲’还知道‘子曰’的后面多半跟着冒号而‘某日’后面跟着干支或事件。这模型就像一个读过万卷古书的老学究专门帮OCR纠正那些犹豫不决的字。”小菜问“那要是有两种解释在古文里都通呢比如‘之’和‘也’混了”“那就保留原字标黄让人来判。”二黑说“机器只纠正高度确定的错误。不确定的老老实实交给王大姐。这是我们的一条铁律——宁可不改不可改错。古籍学者最怕的不是错字而是机器自作主张把原本正确的字改错了你还看不出来。”三、后处理的第三道工序避讳字自动补全大胖老师从抽屉里拿出一本清代刻本翻到一页指着其中一个字“你们看这个‘玄’字。”小菜凑过去只见“玄”字的最后一点若有若无像是故意没写全。“这是刻板的时候漏墨了”“这是避讳。”二黑接过书“康熙皇帝叫玄烨所以清代刻书里‘玄’字必须缺最后一点这叫‘缺笔避讳’。乾隆叫弘历‘弘’字也要缺笔。还有直接改字的比如把‘玄’改成‘元’。古籍里这种避讳字到处都是传统OCR根本不认识这些残字要么跳过要么乱猜。”大胖老师点头“我们是怎么处理的呢两个手段。第一在OCR模型训练阶段用数据增强——随机擦除字形的部分笔画模拟缺笔效果强迫模型学会根据残余笔画推断原字。第二在后处理阶段加载一个避讳字映射表记录了清代所有皇帝的名字和对应的避讳规则。当OCR输出一个低置信度的字且上下文提示它可能是避讳字时系统自动补全。比如‘X之又X’前后都是‘玄’中间那个缺笔的残字自动恢复为‘玄’。”“但这里有一个分寸。”二黑强调“自动补全只适用于出版时间明确的清刻本。如果是明代以前的书就没有避讳问题缺笔就是真缺笔可能是虫蛀或刻工失误不能乱补。所以我们的避讳字模块会根据用户输入的书籍元数据——年代、版本——来判断是否启用。宋代刻本避讳规则完全不一样是避赵匡胤的‘匡’、赵昚的‘昚’。这个映射表是我们请历史系的教授帮忙整理的花了好几个月。”小菜感叹“原来一个缺笔字背后还藏着这么深的历史知识。”大胖老师笑了“这就是古籍OCR和普通OCR的本质区别。普通OCR只需要认识字古籍OCR需要理解字背后的历史。没有领域知识代码写得再好也没用。”四、后处理的第四道工序异体字标准化策略“接下来这个工序是我们被用户骂出来的。”大胖老师苦笑“最开始我们的系统输出是‘原字原样’——OCR在古书上看到什么异体字就输出什么。结果被两个用户同时骂。”二黑接过话“学者骂我们说‘你们怎么把异体字改成简体了我研究的就是字形演变要的就是原字’普通读者骂我们说‘这个字我不认识你们能不能把它变成现在的标准写法’同一套输出两种完全相反的需求。”“这就是异体字标准化的两难。”大胖老师在白板上写了几个例子羣/群、峽/峽、衞/衛、説/說。“古籍里一个‘群’字可能有四五种写法。学者需要原汁原味普通读者需要现代标准。怎么同时满足”“我们的解决方案是输出两个版本。”二黑调出系统设置页面“默认导出的TXT和双层PDF保留原字原样——OCR看到‘羣’就输出‘羣’。但同时系统在后台做了一个异体字映射表包含了三万多条异体字到标准字的对应关系。用户可以在设置里勾选‘异体字标准化’勾上之后‘羣’自动映射为‘群’‘衞’变成‘衛’方便大众阅读和全文检索。”“更精细的做法是双层PDF里保留原字但在搜索索引里同时包含原字和标准字。你搜‘群’能搜到‘羣’搜‘羣’也能搜到‘羣’。”大胖老师补充“这个功能对学术研究特别友好。以后我们还计划支持用户自定义映射表——有些学者研究的就是异体字他们可以上传自己的映射规则。”小菜感慨“原来同一个字给不同的人看要长不同的样子。”二黑推了推眼镜“这就是工程。技术不是做最炫的功能是做最对的选择。”五、后处理的第五道工序双层PDF的“隐身文字术”“终于讲到最后一关了。”大胖老师打开一份双层PDF“这是文渊慧典最受欢迎的输出格式。你们看画面是原汁原味的古籍扫描件发黄的纸、模糊的藏书印、甚至虫蛀的小洞都原样保留。但是——”他鼠标一划竟然选中了一行文字复制粘贴到记事本里一字不差。“底层是原始图片层上面叠加了一层透明文字层。”二黑调出结构示意图“文字坐标是版面分析给的——每一行、每一个字的精确位置都记录在案。生成双层PDF用的是PyMuPDF它支持插入透明文本框。我们给每个字或词放一个不可见的矩形框字体颜色设为白色字号极小——小到肉眼完全看不见但PDF阅读器能识别为文字。”“这样做的好处是什么”小菜问。“好处太多了。”大胖老师掰着手指“第一看着是原书能引用、能作为学术证据。第二文字可搜索——你搜‘子曰’直接跳转到那一页那个位置。第三可复制——学者写论文引用不用手敲直接复制粘贴再标出处。第四兼容性好——任何标准的PDF阅读器都能打开不需要专用软件。第五长期保存——PDF格式是国际标准五十年后还能打开不像某些私有格式软件一死数据就废。”“不过有一个细节。”二黑补充“双层PDF的文字层是透明的所以对字体的要求极低——因为我们根本不用字体显示文字只是用它占位。这就绕过了古籍数字化一个常见的大坑很多古籍用字在现代字体里根本没有导致文本层显示为乱码或空白。我们不给它显示的机会直接隐身只留搜索功能。这招叫‘隐身文字术’。”小菜试着搜了一下“玄”字果然瞬间跳转而且避讳缺笔的那个残字也被搜出来了。“避讳字也能搜”“能。因为我们在文字层里同时嵌入了原字和补全后的标准字。你搜‘玄’能找到残缺的‘玄’你搜‘元’清代避讳改字也能找到。这是两个版本的索引并存各取所需。”六、后处理的最后一步标准格式导出与数据对接“除了双层PDF系统还支持纯文本TXT和带格式的Word导出。”大胖老师继续“但真正的重头戏是ALTO XML。”“ALTO XML是国际古籍数字化领域最通用的结构化格式。”二黑解释“它可以把每一页、每一行、每一个字的坐标、置信度、识别结果全都结构化地存下来。比如某个字被标黄了ALTO文件里就有对应的标签。这样我们的识别结果可以直接导入任何支持ALTO的数字图书馆系统实现跨平台互操作。”“这是一张‘长期饭票’。”大胖老师比喻“王大姐今天用文渊慧典识别一批书导出ALTO XML存着。十年后不管OCR技术怎么升级不管文渊慧典还在不在只要数据是ALTO标准格式未来任何系统都能读取、能更新、能继续用。这才是真正的‘数字化’不是锁死在今天的软件里。”七、后处理的三个“差点翻车”瞬间第一翻语言模型把对的改错了“有一次语言模型把‘未之有也’自动纠正成了‘未之者也’因为它觉得‘者也’比‘有也’高频。但原文就是‘未之有也’出自《孟子》。二黑发现了这个问题加了一条规则如果原文置信度本身就高于0.9语言模型不能强行纠错。宁可漏网不可妄改。”第二翻避讳字把不是避讳的字补了“有一页宋版书‘玄’字因为虫蛀缺了点。系统一看清刻本不对是宋版。但之前的版本没做好年代判断自动补全了。结果一个好好的虫蛀‘玄’被硬生生补成了避讳缺笔再补全的‘玄’绕了一圈。后来加了年代判断宋版不启用清代避讳规则才解决。”第三翻双层PDF把透明文字印出来了“有个用户打印双层PDF打印机设置成了‘打印注释和标记’结果透明文字层全被印成了小黑点糊在古籍图像上。我们紧急更新了导出设置把文字层的‘可打印’属性改为False。现在屏幕阅读正常打印只出图像层。吃一堑长一智。”八、下期预告大胖老师看看窗外天色“后处理的魔法今天就讲到这儿。从一堆乱码到一本可搜索的双层PDF我们走了五道工序。但工序走完了不代表项目做完了。”二黑收起笔记“接下来才是真正的考验——实战。我们这套系统从实验室到王大姐的电脑中间隔着一百个意想不到的bug。怎么填坑怎么测试怎么让它在老爷机上跑得稳如老狗这才是最考验工程功力的地方。”小菜举手“是不是该讲我们被内存泄漏折磨了三天最后发现是一个变量名写错了的那次”“对。”大胖老师苦笑“下期开发实战与问题解决。主题就叫——”《开发文渊慧典这两年我们填过的坑比大胖老师的枸杞还多》“把你内存泄漏那次的故事准备好。二黑把‘玄学代码’那个bug的复现步骤整理一下。下期咱们把开发过程中的十大翻车现场一个一个摆出来。”小菜揉了揉手腕二黑打开了bug跟踪系统大胖老师拧开保温杯续上了今天的第四杯枸杞水。实验室的窗外校图书馆的灯已经全亮了。王大姐刚用文渊慧典跑完了一本明天读者要用的方志在群里发了一条消息“这系统越来越快了茶还没凉书就认完了。”大胖老师看到这条消息把手机转向二黑和小菜“听见了吗这才是我们最好的技术指标——茶还没凉。”本文为注水技术版您看看即可不必当真写此文字就是图一乐-
返回列表