如何确定普通话的Levenshtein距离?

时间:2012-09-12 02:56:51

标签: c++ unicode cjk levenshtein-distance edit-distance

我们正在开发一个系统,使用UTF-8,UTF-16和UTF-32 Unicode字符标准对50多种国际语言进行模糊匹配。到目前为止,我们已经能够使用Levenshtein距离来检测德语Unicode扩展字符单词的拼写错误。

我们希望扩展此系统以处理以Unicode表示的中文表意文字。我们如何在相似的汉字之间进行Levenshtein距离计算?

2 个答案:

答案 0 :(得分:17)

首先,只是为了澄清:中文字符不等同于德语或英语。大多数你认为是单词的东西(使用"单词"的语义或句法定义)由1-3个字符组成。通过将Levenshtein距离表示为UCS-2或UCS-4代码点的序列,可以直接将Levenshtein距离应用于这些字符序列。由于大多数单词很短(特别是长度为1或2个字符的单词),但它的用途可能有限。

但是,由于您的问题是关于 个别字符 之间的编辑距离,我认为需要采用不同的方法,而且确实可能​​非常困难。

首先,您必须将每个字符表示为它所包含的组件/笔画的序列。有两个问题:

  • 某些组件本身包含更小的组件,因此如何将一个角色分解为" atomic"组件没有唯一定义。如果你将其降低到单个笔划的水平,则需要对每个笔划(角色,形状,方向等内的位置)进行表征。我并不认为每个人都这样做(如果有人告诉我,我最感兴趣的话)。

  • 您需要将笔画或组件放入顺序。明显的候选者是角色的规范笔画顺序,在lexica中有描述,甚至还有带有动画笔画顺序图的字典网站。但是,我所知道的数据源(日语)会将这些动画生成为位图图形序列;我从未见过以适合编辑距离计算的形式表示笔画序列(甚至是单个笔画名称)的人或机器可读代码。

然而,您可以尝试的最后一件事是渲染角色字形并根据需要更改多少像素(或矢量)来计算编辑距离把一个角色变成另一个角色。我曾经在OCR后期校正的背景下对拉丁字符和字符组合(以像素为基础)做了这个,结果非常令人鼓舞。


快速回答larsmans评论如下:Unicode标准定义了两个相关概念(下面我引用6.0 version, chapter 12):

  1. 基于部首和中风计数的指数。每个汉字由几个部分组成,一个是激进的。基础/笔划计数索引是按部首排序的字符列表(即,共享相同基团的所有字符组合在一起),并且每个基础特定组内部按字符其余部分中使用的笔划数排序。不幸的是,即使这不是唯一的定义 - 有些字符的根本由不同的传统词汇定义不同,并且笔画计数也很困难。以下是Unicode标准所说的内容:

      

    为了加快在代码表中定位特定的汉字表意字符,Unicode网站上提供了基本笔画索引。 [...]   激进中风信息最有影响力的权威是十八世纪   康熙字典,其中包含214个激进分子。今天使用康熙激进派的主要问题是,许多简化字符很难在214中的任何一个下进行分类   康熙激进分子。结果,引入了各种现代激进集。然而,没有一个是普遍使用的,214康熙的激进分子仍然是最知名的。 [...]   Unicode激进笔画图基于康熙激进派。 Unicode标准   遵循许多不同来源进行根治性卒中分类。哪两个来源   对于给定角色的激进或笔画计数存在争议,角色在激进笔画图中的两个位置都显示出来。

    请注意,即使我们假设激进/笔划索引是明确和正确的,它也不足以作为将角色转换为组件序列的信息源,因为角色的唯一组成部分是完全的由此描述的是激进派。

  2. 表意文字描述序列(12.2节):Unicode定义了字符基本组成部分的代码点(大多数字符本身可以作为独立字符使用),并且有一些代码点用于将它们粘合在一起形成一个描述更复杂字符组成的组件序列。所以这种方式与组合字符类似,但有一些重要区别:

    1. 组件的顺序没有唯一定义
    2. 此类序列没有定义渲染机制
    3. 没有从普通字符到相应的表意文字描述序列的映射(尽管标准提到这种映射在某种程度上存在于它们用于编译汉字符集的源中)。
    4. 标准建议使用表意描述序列来描述任何现有代码点未表示的复杂或罕见的特征;但它明确地不鼓励使用描述序列代替普通字符:

        

      特别是,表意文字描述序列不应用于提供替代方案   数据交换中编码的表意文字的图形表示。搜索,整理,   然后,其他基于内容的文本操作将失败。

答案 1 :(得分:0)

我写了一个python软件包fuzzychinese来纠正中文单词的拼写错误。

就像@jogojapan所说的那样,如果您真的想计算Levenshtein距离,则使用自由基笔画之类的子字符结构更有意义。您可以使用Stroke()中的Radical()fuzzychinese类分解字符,然后计算Levenshtein距离。

但是,我不确定Levenshtein距离是否可以正确纠正中文拼写错误。在我写的程序包中,我计算了n-gram笔画的tf–idf向量,并使用余弦相似度来匹配单词。