简介:OCR将汉字视为不可拆分的整体,导致AI写字评分只有对错两档,模型难以从错误中学习改进。本文从汉字二维积木结构出发,剖析传统评分机制的缺陷,介绍构型分解思路与分级打分策略,为开发者提供一套可落地的技术方案,让生成模型真正学会“哪里错了、错到什么程度”。
在生成式模型的质量优化流程中,强化学习已成为常见的后训练手段。其基本框架是:模型生成候选结果,由一个“裁判”模块对结果打分,模型根据分数信号调整参数。这套范式的关键假设在于——裁判的打分必须是有梯度的,即分数要能反映生成质量的连续变化。
当生成目标从通用图像转向中文字形图像时,裁判角色通常由OCR(光学字符识别)模型承担。逻辑非常直接:把生成图片中的文字区域截取出来,送入OCR识别,识别结果与目标文字一致则给高分,不一致则给低分甚至零分。
这个逻辑在英文场景下基本够用。英文的最小单位是字母,26个字母的排列组合构成单词,错误模式相对离散——要么拼错了某个字母,要么整个词不对。OCR对英文字母的识别鲁棒性也较高,评分信号相对清晰。
但汉字的情况截然不同。
汉字与英文最根本的差异在于构型(character configuration)。英文是线性序列,字母从左到右排列;汉字是二维空间中的积木式组合——偏旁部首按照左右、上下、包围、半包围等空间关系拼合而成。
举几个直观的例子:
这种结构的复杂度意味着,一个汉字可能出现的错误模式远多于英文单词。笔画写错一笔、偏旁写错半边、空间关系错位、部件比例失调——每一种都是不同性质的错误,其严重程度也各不相同。
然而,OCR裁判并不区分这些。它的输出只有两种:识别对了,或者识别不出来。
假设一个生成模型正在学习写“尬”字。它可能生成以下两种结果:
对于OCR裁判来说,第一种情况中,如果OCR模型恰好能识别出这个错字并映射到某个形近字,结果可能是“不对,0分”;如果OCR直接无法识别,结果同样是“0分”。第二种情况则是“对了,1分”。
问题在于:第一种情况和完全乱写一个无关字符,得到的分数是一样的。模型无法从“0分”这个信号中得知:自己是偏旁写错了、结构写反了、还是笔画多了一笔。它只知道“错了”,但不知道“错在哪里、错了多少”。
这就好比批改一份100道选择题的试卷,不管学生错一道还是错九十道,分数统统是零分。这样的打分方式完全无法告诉学生“你哪里需要改进”,模型也就学不到该往哪个方向优化。
更隐蔽的问题在于假阳性。论文中给出了一个典型案例:生成图里有个“尬”字结构出了问题,专门的OCR模型老老实实地把它认成了另一个形近字,打0分——这是正确的判断。但换成多模态大模型去识别时,它结合上下文语境,“猜”出了正确答案,打了1分。这其实是一个假阳性:图上那个字形明明是错的,模型只是靠语言能力蒙对了而已。
还有一类专门检测“写错字”的工具,能准确判断出字形结构有问题,但处理方式是把整个字标记成一个异常符号,直接打0分。这种方法虽然不会被语言模型的“脑补”骗到,但同样是非黑即白的判断:对,或者错,中间没有灰色地带。
汉字的错误本来就有程度之分。从技术角度,我们可以将生成字形的质量划分为多个层级:
| 层级 | 描述 | 示例 |
|---|---|---|
| L5 完全正确 | 笔画、结构、比例均正确 | “尬”字标准写法 |
| L4 轻微瑕疵 | 笔画粗细不均或比例微调 | “尬”字右半稍宽 |
| L3 部件错误 | 某个偏旁写错但结构正确 | “尬”字右半写成“尤” |
| L2 结构错位 | 左右/上下关系颠倒 | “尬”字左右互换 |
| L1 严重变形 | 多个部件错误或严重扭曲 | 只能看出大致轮廓 |
| L0 完全无关 | 无法辨认或为其他字符 | 随机笔画组合 |
一个理想的评分机制应当能够区分L0到L5,并给出连续的分数信号。这样模型才能知道:当前生成结果处于哪个层级,距离目标还有多远,应该优先改进哪个方面。
要让AI真正“学会”写对汉字,需要从评分机制的根本上做改造。核心思路是:将汉字从不可拆分的黑箱,拆解为可独立评估的构型组件。
首先需要建立一个汉字构型知识库,将每个汉字拆解为:
这个知识库可以基于通用的汉字构型数据库构建,不依赖特定厂商的专有资源。
评分模块不再依赖单一OCR识别结果,而是从多个维度分别评估:
def score_character(generated_img, target_char, config_db):"""多维度汉字生成质量评分返回0-1之间的连续分数,以及各维度子分数"""target_parts = config_db.get_parts(target_char)target_layout = config_db.get_layout(target_char)# 维度1:部件识别——每个部件是否被正确生成part_scores = []for part in target_parts:part_img = crop_by_layout(generated_img, part.position)part_score = recognize_part(part_img, part)part_scores.append(part_score)# 维度2:空间关系——部件之间的相对位置是否正确layout_score = evaluate_layout(generated_img, target_layout)# 维度3:笔画完整性——关键笔画是否存在stroke_score = evaluate_strokes(generated_img, target_char)# 加权综合final_score = (0.4 * mean(part_scores) +0.3 * layout_score +0.3 * stroke_score)return final_score, {"part_scores": part_scores,"layout_score": layout_score,"stroke_score": stroke_score}
基于多维度评分,可以生成更丰富的反馈信号:
这种分级反馈信号比单一的“对/错”二元信号信息量大得多,能显著加速模型收敛。
在实际工程落地中,还需要考虑以下问题:
评分模块的鲁棒性。部件识别模型本身也可能出错,需要引入置信度机制。当部件识别置信度低于阈值时,该维度的评分权重应降低,避免误导生成模型。
计算开销。多维度评分比单次OCR调用开销更大。可以采用缓存机制:对同一目标字符的构型分解结果进行缓存,避免重复计算。
与现有训练流程的集成。分级打分模块可以作为强化学习中的奖励函数,替换原有的OCR裁判。在训练初期,可以使用较粗粒度的评分;随着模型能力提升,逐步启用更细粒度的维度。
评估基准的建立。需要构建一套包含不同错误层级的汉字生成测试集,用于验证评分模块是否真正区分了不同严重程度的错误。
汉字生成的质量优化,核心瓶颈不在于生成模型本身的能力,而在于评分信号的信息量。OCR裁判将汉字视为不可拆分的黑箱,只能给出“对/错”的二元判断,导致模型无法从错误中学习“错在哪里、错了多少”。
解决路径是明确的:拆解汉字构型,建立多维度评分体系,提供分级反馈信号。这不仅是技术上的改进,更是对汉字本质结构的尊重——汉字本来就是二维积木,就应该用积木的方式去评估。
对于开发者而言,这套思路可以迁移到其他复杂结构化生成任务中:当评估指标过于粗粒度时,拆解目标结构、设计多维度评分,往往是提升生成质量的关键杠杆。