65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 Double Metaphone 实现语音(“听起来像”)姓名搜索 第二部分:Visual Basic 和关系数据库解决方案

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.79/5 (14投票s)

2003年7月26日

11分钟阅读

viewsIcon

152367

downloadIcon

4176

介绍围绕作者 C++ 实现的 Double Metaphone 的 COM 包装器,并演示了如何在 Visual Basic 中使用此 COM 包装器来语音搜索姓名列表以及数据库表中的姓名。

摘要

简单的信息搜索(如姓名查找、单词搜索等)通常是基于精确匹配的标准实现的。然而,考虑到同音(发音相同)词汇和姓名的多样性,以及人们容易拼写错误姓氏的倾向,这种简单的标准通常会产生不理想的结果,表现为结果集减少、丢失因字母拼写错误或不同国家拼写方式而不同的记录。

本系列文章讨论 Lawrence Phillips 的 Double Metaphone 语音匹配算法,并提供了一些有用的实现,这些实现可以用于各种解决方案,以创建更有用、更有效的数据库和其他集合中专有名词的搜索。

引言

本系列文章讨论 Double Metaphone 算法在语音搜索姓名数据方面的实际应用,使用作者为 C++、COM(Visual Basic 等)、脚本客户端(VBScript、JScript、ASP)、SQL 和 .NET(C#、VB.NET 以及任何其他 .NET 语言)编写的实现。有关 Double Metaphone 算法本身以及 Phillips 原始代码的讨论,请参阅 Phillips 在 2000 年 6 月 CUJ 上的文章,可在此处 找到

第一部分介绍了 Double Metaphone,并描述了作者的 C++ 实现及其用法。第二部分讨论了如何在 Visual Basic 中使用作者的 COM 实现。 第三部分演示了如何在 ASP 和 VBScript 中使用 COM 实现。 第四部分展示了如何使用作者的扩展存储过程在 SQL Server 中执行语音匹配。 第五部分演示了作者的 .NET 实现。最后, 第六部分对语音匹配的替代方案进行了概述,并提供了其他资源的链接。

背景

第一部分的本系列文章讨论了 Double Metaphone 算法、其起源和用法以及作者的 C++ 实现。虽然本节总结了该文章的关键信息,但仍鼓励读者阅读全文,即使读者没有 C++ 经验。

Double Metaphone 算法由 Lawrence Phillips 开发,并发表在 2000 年 6 月的 C/C++ Users Journal 上,属于“语音匹配”或“语音编码”算法类别。这些算法试图检测单词之间在语音上的(“听起来像”)关系。例如,语音匹配算法应该能检测出“Nelson”和“Nilsen”之间的强语音关系,而“Adam”和“Nelson”之间则没有语音关系。

Double Metaphone 的工作原理是根据一个单词生成一个或两个语音键。这些键代表单词的“声音”。典型的 Double Metaphone 键长度为四个字符,这倾向于在特异性和结果的通用性之间产生理想的平衡。

第一个(主)Double Metaphone 键代表源单词的美式发音。所有单词都有一个主 Double Metaphone 键。

第二个,即备用,Double Metaphone 键代表一种备用的、国家化的发音。例如,许多波兰姓氏被“美国化”,产生两种可能的发音:原始波兰语和美式发音。因此,Double Metaphone 会为某些单词计算备用键。请注意,绝大多数(非常粗略地估计,90%)单词不会产生备用键,但当计算出备用键时,它可能在匹配单词方面发挥关键作用。

要比较两个单词的语音相似度,需要计算它们各自的 Double Metaphone 键,然后比较每种组合:

  • 单词 1 主键 - 单词 2 主键
  • 单词 1 主键 - 单词 2 备用键
  • 单词 1 备用键 - 单词 2 主键
  • 单词 1 备用键 - 单词 2 备用键

显然,如果给定的单词没有生成上面某个比较中的键,那么涉及该键的比较就不会执行。

根据以上哪种比较匹配,会计算出匹配强度。如果第一个比较匹配,则两个单词具有很强的语音相似性。如果第二个或第三个比较匹配,则两个单词具有中等语音相似性。如果第四个比较匹配,则两个单词具有最小的语音相似性。根据具体的应用需求,可以从匹配结果中排除一个或多个匹配级别。

COM 实现

作者创建了一个 COM 组件,该组件封装了 第一部分中讨论的 C++ Double Metaphone 实现。此 COM 组件可以从 Visual Basic、Microsoft Access、Visual FoxPro、Delphi 以及任何其他 COM 兼容语言调用。虽然本文档重点介绍 Visual Basic,但这些概念适用于任何语言。

本文将演示如何使用 VB Word Lookup 示例应用程序,该应用程序是 Word Lookup C++ 示例的 Visual Basic 版本(来自 第一部分),来使用 Double Metaphone COM 组件。VB Word Lookup 从文本文件中读取 21,000 个姓名列表,然后构建一个匹配 Double Metaphone 语音键的映射,以及所有产生这些语音键的单词。Visual Basic 版本将使用 Dictionary 类将语音键映射到与该语音键匹配的单词数组。查找是通过使用搜索单词的语音键查询 Dictionary 类来执行的;与搜索单词的语音键关联的数组中的所有字符串都是搜索单词的语音匹配项。

使用 MetaphoneCOM.DoubleMetaphoneString

使用 Double Metaphone 实现的第一步是使用“项目 | 引用”菜单将 Double Metaphone 组件的引用添加到项目中。

请注意,在打开“引用”对话框之前必须注册该组件。要注册该组件,请打开命令提示符,切换到包含 MetaphoneCOM.dll 的目录,然后输入以下命令:

regsvr32 MetaphoneCOM.dll

每次使用 Double Metaphone 的机器上只需注册一次该组件。

将 Double Metaphone 添加到项目引用后,就可以像其他组件一样使用它了。例如,查看 VB Word Lookup 中 btnFind_Click 处理程序中的这段代码:

'Compute the double metaphone keys for the search word
Dim mphone As New MetaphoneCOM.DoubleMetaphoneString
Dim primaryKey As String
Dim alternateKey As String
    
mphone.ComputeMetaphoneKeys searchWord, primaryKey, alternateKey

通过检查 VB Word Lookup 代码,可以清楚地发现使用 Double Metaphone 非常简单。事实上,VB Word Lookup 中最复杂的部分不是 Double Metaphone,而是使用 Dictionary 类将语音键映射到匹配这些语音键的单词的变体数组。这在概念上与 C++ 版本相同,后者使用类似的(尽管类型更安全且效率更高)容器配置。

另外请注意,与 Word Lookup 不同,VB Word Lookup 不会根据哪些键匹配哪些键来计算匹配分数。这留给读者作为练习。

使用 MetaphoneCOM.DoubleMetaphoneShort

正如本系列 第一部分中所述,Double Metaphone 有一种优化方法,即将四字符的语音键表示为无符号短整型(Visual Basic 中的 Integer)。这种优化也通过 COM 组件的形式暴露出来,即 MetaphoneCom.DoubleMetaphoneShort 类。其用法与 DoubleMetaphoneString 相同,只是它生成的键是 Integer 而不是 String。尝试修改 VB Word Lookup 以使用无符号短整型优化,并注意由此产生的查找性能变化。

请注意:这种优化对于数据库应用程序尤其重要,它们可以从减小的键大小(Integer 是两个字节,而 Metaphone 键通常包含终止 NULL 在内,共五个字节)以及更重要的是,提高的比较速度中获益良多。现代 CPU 包含的指令可以在一个时钟周期内比较两个 Integer,而比较两个 String 则需要多个时钟周期,这意味着基于 Integer 的搜索比基于 String 的搜索速度快得多。

Double Metaphone 与关系数据库

与 C++ 不同,Visual Basic 对关系数据库具有广泛的内置支持。因此,作者将 Double Metaphone 在数据库应用程序中的讨论推迟到本文,以便更容易使用 VB 而不是 C++ 来演示概念。尽管如此,本节中的概念特定于关系数据库,而不是特定数据库,当然也不是特定语言。

到目前为止,所有 Double Metaphone 应用的示例都有些不切实际。虽然作为演示很有说服力,但使用静态、内存中的容器来映射预定义的姓名列表及其语音键,在一个关键方面有所欠缺:很少有现代应用程序基于小型、静态数据集。更可能的情况是,它们基于包含结构化信息的数据库表,并且数据更新的频率接近实时。将 Word Lookup 示例的模型改编到这种场景会很困难且耗时,而且结果会很糟糕。

相反,必须设计一种存储语音键并执行语音搜索的方法,该方法能够利用关系数据库的固有优势。具体来说,关系数据库系统在根据特定搜索条件(通常使用结构化查询语言 (SQL) 表示)快速搜索大量结构化数据方面表现出色。

正如许多读者可能已经猜到的那样,显而易见的解决方案是在数据库本身中计算并存储要搜索的数据的 Metaphone 键。要对这些数据执行语音搜索,只需计算搜索项的语音键,然后构建一个 SQL 查询来检索这些数据,其中语音键与搜索键匹配。尽管在实现时这可能变得相当复杂,尤其是在搜索多词数据时,但概念本身却很简单。

为了演示,将使用一个称为 VB Word DB Lookup 的 VB Word Lookup 示例的变体。此版本操作一个 Microsoft Access 2000 数据库,该数据库包含一个名为 Words 的表,其中包含以前示例中使用的单词列表,以及每个单词的 Double Metaphone 键的无符号短整型表示,这些键已经过计算并存储在表的单独列中。包含键的列已建立索引以获得最大性能。

请注意,选择 Access 主要是为了方便;大多数开发人员都安装了它,并且其基于文件的数据库无需额外配置即可轻松交换。有经验的开发人员应该能够轻松地将此示例改编到 SQL Server、DB2、Oracle 等。

VB Word DB Lookup 的源文件以及它操作的 Access 数据库包含在源档案中,此处不再详述。要点是 VB Word DB Lookup 生成的 SQL,用于检索语音匹配结果。要探索 SQL,请考虑一个示例搜索,该搜索是通过在搜索框中输入“Patricia”(它有一个备用 Metaphone 键)生成的:

select word 
from Words 
where
(key1 = -25654) 
or (key2 = -25654) 
or (key1 = -25651) 
or (key2 = -25651)

此 SQL 执行的搜索逻辑与 Word Lookup 和 VB Word Lookup 应用程序相同,但仅用一行 SQL 代码代替了数十行 C++ 或 VB 代码。在这种情况下,-25654 是搜索词“Patricia”的主 Metaphone 键的无符号短整型形式,而 -25651 是备用 Metaphone 键。 WHERE 子句执行了比较两个单词以进行语音相似性测试的所有四种可能的测试,首先将表中文档的主键与主搜索键进行比较,然后将备用键与主搜索键进行比较,接着将主键与备用搜索键进行比较,最后将备用键与备用搜索键进行比较。

虽然 SQL 版本显然要简单得多,但使用关系数据库进行语音匹配具有更重要的意义。首先,数据库引擎实现了复杂的索引和优化技术,特别是对于包含键的索引列。因此,搜索速度会显著提高。

其次,许多现代数据库引擎支持以太字节或更大的数据集。因此,通过使用关系数据库,应用程序可以以惊人的速度和出乎意料少的编程工作量对非常大的数据集执行语音匹配。

第三,也许最重要的是,关系数据库是动态的。正如编写过数据库应用程序的任何人所知,当数据库可以被修改和查询时,它们会更强大。数据库引擎允许数千个并发连接查询和修改数据,并使用锁来防止数据损坏。用各种语言编写的客户端可以访问和更新数据库,无论是在同一台机器上还是跨越世界。数据库已经是信息中心;在数据库层面添加语音匹配显然是最有意义的。

结论

本文演示了如何在 Visual Basic 中使用 Double Metaphone COM 实现,并介绍了 Double Metaphone 驱动的语音匹配与关系数据库的结合使用。从本文可以看出,在一般语音匹配以及与关系数据库进行语音匹配时使用 Double Metaphone,为开发极其强大、易于使用的应用程序提供了显著的机会,同时付出了最小的计算和程序员努力。

有关更多 Double Metaphone 实现示例,包括其他关系数据库应用程序,请继续阅读系列中的其余文章。 第三部分演示了如何在 ASP 和 VBScript 中使用 COM 实现,包括针对数据库的语音搜索。 第四部分介绍了作者的 SQL Server 扩展存储过程,该过程允许从 SQL 内部计算 Double Metaphone 键。第四部分还讨论了关系数据库语音匹配解决方案的优化,并解决了一些与数据库相关的实际实现问题。 第五部分探讨了作者的 .NET Double Metaphone 实现,并包含了一个针对关系数据库执行语音搜索的示例。最后, 第六部分通过考察替代语音匹配技术以及提供其他资源和 Double Metaphone 实现的链接,结束了 Double Metaphone 的讨论。

历史

  • 2003年7月22日 首次发布。
  • 2003年7月31日 添加了系列文章之间的超链接。

文章系列

© . All rights reserved.