产品名称的模糊匹配

Posted

技术标签:

【中文标题】产品名称的模糊匹配【英文标题】:Fuzzy matching of product names 【发布时间】:2010-10-10 08:43:03 【问题描述】:

我需要将来自不同来源的产品名称(相机、笔记本电脑、电视等)自动匹配到数据库中的规范名称。

例如“Canon PowerShot a20IS”“佳能的NEW powershot A20 IS”“数码相机Canon PS A20IS” 应该都匹配“Canon PowerShot A20 IS”。我已经通过一些附加的启发式(删除明显的常用词,为数字更改分配更高的成本等)处理了 levenshtein 距离,这在一定程度上有效,但不幸的是还不够好。

主要问题是,即使是相关关键字的单个字母变化也会产生巨大的差异,但要检测哪些是相关关键字并不容易。以三个产品名称为例:Lenovo T400Lenovo R400New Lenovo T-400, Core 2 Duo 从任何标准来看,前两个都是非常相似的字符串(好吧,soundex 在这种情况下可能有助于区分 T 和 R,但名称也可能是 400T 和 400R),第一个和第三个彼此相距很远,因为字符串,但是是同一个产品。

显然,匹配算法不可能 100% 精确,我的目标是自动匹配大约 80% 的名称,并且置信度很高。

非常感谢任何想法或参考

【问题讨论】:

【参考方案1】:

我认为这将归结为区分 Lenovo 等关键词和 New 等谷壳。

我会对名称数据库进行一些分析以识别关键词。您可以使用类似于用于生成词云的代码。

然后我会手动编辑列表以删除任何明显的谷壳,比如也许 New 实际上很常见但不是关键。

然后,您将获得可用于帮助识别相似性的关键词列表。您可以将“原始”名称与其关键字相关联,并在比较两个或多个原始名称的相似性(字面意思是共享关键字的百分比)时使用这些关键字。

无论如何都不是一个完美的解决方案,但我认为您不会期待一个?

【讨论】:

【参考方案2】:

这里的关键理解是您确实有一个适当的距离度量。这实际上根本不是你的问题。您的问题在于分类。

让我举个例子。假设 Foo X1 有 20 个条目,Foo Y1 有 20 个条目。您可以放心地假设它们是两组。另一方面,如果 Bar X1 有 39 个条目,Bar Y1 有 1 个条目,则应将它们视为一个组。

现在,距离 X1 Y1 在两个示例中是相同的,那么为什么分类会有所不同?这是因为 Bar Y1 是异常值,而 Foo Y1 不是。

有趣的是,您实际上不需要做很多工作来预先确定这些组。您只需进行递归分类。您从每个组的节点开始,然后为两个最近的节点添加一个超级节点。在超级节点中,存储最佳假设、其子树的大小和其中的变化。由于您的许多字符串都是相同的,您很快就会得到具有相同条目的大型子树。递归以包含树根的超级节点结束。

现在将规范名称映射到这棵树。您会很快看到每个都将匹配整个子树。现在,使用这些树之间的距离来选择该条目的距离截止。如果您在数据库中同时拥有 Foo X1 和 Foo Y1 产品,则截止距离将需要更低以反映这一点。

【讨论】:

【参考方案3】:

我认为edg的答案是正确的——你需要区分关键词和绒毛。

上下文很重要。以你的例子为例,Core 2 Duo 在查看 T400 的两个实例时是绒毛的,但在查看 CPU OEM 包时则不然。

如果您可以在数据库中标记产品名称规范形式的哪些部分更重要并且必须以一种或另一种形式出现以识别产品,那么您应该这样做。也许通过使用某种语义标记?你能负担得起人工标记数据库的费用吗?

您可以尝试为“T-400”、“T400”、“T 400”等内容定义等价类。也许有一组规则说“数字比附加在这些数字上的字母更牢固”。

根据制造商、型号等细分案例可能是一个不错的方法。我建议您查看术语发现技术以尝试实现这一目标:http://www.worldcat.org/isbn/9780262100854

在一个主要由规则驱动的灵活框架中设计所有内容,其中规则可以根据您的需求和新出现的不良模式(阅读:破坏您的算法的事情)进行修改,这也是一个好主意。这样您就可以根据真实世界的数据提高系统的性能。

【讨论】:

【参考方案4】:

您也许可以为此使用trigram search。我必须承认我从未见过实现索引的算法,但见过它在制药应用中的工作,它确实可以很好地应对拼写错误的药物名称。您也许可以将相同类型的逻辑应用于此问题。

【讨论】:

【参考方案5】:

这是record linkage的问题。 dedupe python library 提供了完整的实现,但是即使你不使用python,文档也有good overview of how to approach this problem。

简而言之,在标准范式中,此任务分为三个阶段

    比较字段,在本例中只是名称。为此,您可以使用一个或多个比较器,例如编辑距离(如 Levenshtein 距离)或余弦距离(比较常用词的数量)。 将距离分数数组转换为一对记录确实是关于同一事物的概率 将这些成对概率分数聚集到可能都指向同一事物的记录组中。

【讨论】:

【参考方案6】:

您可能希望创建忽略型号的字母/数字组合的逻辑(因为它们总是非常相似)。

【讨论】:

【参考方案7】:

对此类问题没有任何经验,但我认为一个非常幼稚的实现是对搜索词进行标记,并搜索恰好包含任何标记的匹配项。

“Canon PowerShot A20 IS”,例如,标记为:

佳能 Powershot A20 是

这将匹配您希望在结果中显示的每个其他项目。当然,这种策略也可能会产生大量错误匹配。

另一种策略是为每个项目存储“关键字”,例如“相机”、“佳能”、“数码相机”,并根据具有匹配关键字的项目进行搜索。此外,如果您存储了其他属性,例如 Maker、Brand 等,您可以搜索其中的每一个。

【讨论】:

【参考方案8】:

Spell checking 算法浮现在脑海。

虽然我找不到一个好的示例实现,但我相信你可以修改一个基本的拼写检查算法来得出令人满意的结果。即以单词为单位而不是字符。

留在我记忆中的点点滴滴:

    删除所有常用词(a、an、the、new)。什么是“常见”取决于上下文。 获取每个单词的首字母及其长度,并将其作为单词键。 当出现可疑词时,查找具有相同或相似词键的词。

它可能不会直接解决你的问题......但你说你在寻找想法,对吧?

:-)

【讨论】:

【参考方案9】:

这正是我在业余时间解决的问题。我想出的是: 基于关键字缩小搜索范围:

在这种情况下,您可以有一些层次结构:

类型 --> 公司 --> 型号

这样你就可以匹配 一种类型的“数码相机”

公司的“佳能”,您的搜索范围会更窄。

您可以通过引入产品线等来进一步解决这个问题。 但重点是,这可能必须迭代完成。

【讨论】:

这种方法对你有用还是你朝另一个方向走?【参考方案10】:

我们可以使用Datadecision service 来匹配产品。

它将允许您使用统计算法自动匹配您的产品数据。此操作在定义置信度阈值后完成。

所有无法自动匹配的数据都必须通过专门的用户界面进行人工审核。

在线服务使用查找表来存储同义词以及您的手动匹配历史记录。这使您可以在下次导入新数据时改进数据匹配自动化。

【讨论】:

【参考方案11】:

我过去也做过同样的事情。我所做的是使用 NLP 方法; TF-IDF Vectorizer 为每个单词分配权重。例如在你的情况下:

佳能 PowerShot a20IS

佳能 --> 重量 = 0.05(不是一个非常有区别的词) PowerShot --> weight = 0.37(可以区分) a20IS --> weight = 0.96(非常有区别)

这将告诉您的模型哪些词需要关注,哪些词不需要。多亏了 TF-IDF,我有很好的比赛。 但请注意:a20IS 无法识别为 a20 IS,您可以考虑使用某种正则表达式来过滤此类情况。

之后,您可以使用余弦相似度等数值计算。

【讨论】:

以上是关于产品名称的模糊匹配的主要内容,如果未能解决你的问题,请参考以下文章

SQL模糊匹配

SQL两表模糊匹配查询

PowerShell中的模糊字符串匹配

模糊逻辑匹配

如何使用 PHP 对 MYSQL 中的公司名称进行模糊匹配以自动完成?

Python 记录链接、模糊匹配和去重