匹配大型文本数据集——如何更快地匹配?
Matching large datasets of text - how to do it faster?
我已经为数周的时间而苦苦挣扎,寻找在逻辑上和技术上最好的方法,同时尝试以连续、轮换的方式匹配 2 大组文本。
一方面,我们有歌曲及其歌词(大约 3000 万行文本,每行约 1000 个字符),另一方面我们有歌曲歌词类别(约 20K,每行约 50 个字符)。歌词类别指的是歌曲的内容。
每首歌都应该归入一个或多个类别,在我看来,这只能通过比较每个类别中的单词与歌曲歌词的相关性来完成,然后选择全文搜索得分最高的那个(或超过 1 个类别,对于那些得分相同的类别),同时考虑同义词、词干提取、停用词和适当的全文搜索引擎的所有附加功能.如果你有更好的方法来解决这个问题,请不要犹豫给我一个提示。
举个例子,根据歌词,"Unchained Melody"这首歌应该属于:
- 情歌
- 为了我亲爱的,我的爱
- 感到孤独
它的歌词确实包含了该类别(它的整个路径)中包含的所有这些词,包括它们的变形和同义词,多次,所以这个类别的文本应该与歌曲的文本相比排名很好.
所以问题是可以使用哪种方法将所有这些类别文本与所有这些歌曲文本匹配?
请记住,自然地,如今每天发布数千首歌曲,并且类别不断changing/improving甚至有可能彻底改变。
到目前为止,我已经尝试了以下方法:
SQL 保存类别的 Server 2014,链接到在其全文索引中保存歌词文本的 Sphinx 搜索引擎。基于这些构建的应用程序对单首歌曲文本执行 20K 次查询(即,获取每个类别与歌曲文本的相关性),选择排名最好的结果。这意味着要匹配所有歌曲的 20K * 30M 查询。当然,这在40核机器+256GB RAM上需要很长时间,到那时,有新歌和可能的changed/updated类别结构。
这个很有趣:SQL 包含歌词的 Server 2014,链接到包含类别文本的 Sphinx。为每首歌曲匹配类别的查询是通过将歌曲文本拆分为单词来创建的,在它们之间使用 "OR" 运算符,如果在一行中找到更多单词(包含类别文本和来自的文本),则结果排名更高它的完整路径)。结果:更快,因为每首歌曲只有 1 个大查询才能获得其排名靠前的类别,但仍然不够快,而且准确度稍差。
SQL Server 2014 同时包含歌词和类别,启用全文搜索,同时使用第一种方法(没有 Sphinx,只有 SQL' s FT) 在一组有限的类别上最初是由第二种方法产生的(同样,没有 Sphinx,只有 SQL 的 FT),所有的东西都分成数百个异步批次的工作。所以,它是以上两者的结合。结果:更准确,并赋予它全部的力量,更快一点,但仍然不够我认为可能的。匹配所有歌曲和歌词大约需要3天时间。
如果您有任何其他想法可以尝试,我将不胜感激。我对准确性 (40%) 和速度 (60%) 很感兴趣,我真的觉得有更简单的方法来完成这项工作。
就我个人而言,我可能会坚持使用您的 1。但有两个改进
批量更新,而不是简单地 运行 每个 category/document 组合一个查询。 运行 每个类别一个查询 - 并获得所有文档的结果。更少的大查询。您可以通过一些优化来使这些 'big' 查询更加高效。
Delta Updates,而不是每个周期,只是 运行ning 'full' 进程,周期性地使用一个单独的更小的特定系统。知道如何 运行 更集中更新以避免重复工作的人。例如:
您添加一个新类别,只需 运行 其大查询即可找到该类别的文档。删除的类别只会删除记录。 'edit' 到类别,可以是删除后跟插入。
新文档,也可以是只包含新文档的特殊 sphinx 索引(main+delta 索引系统可能已经提供了!)。然后 运行 针对这个小得多的增量索引对每个类别进行主查询。
- 甚至可以使用 'speculative' 系统来减少您需要 运行 的类别数量。例如,将类别中的所有单词塞入批量 BuildKeyword 调用中。这可以让你返回每个单词的点击率,这样你就可以排除没有匹配项的类别(因此不需要 运行 主查询,对于许多类别)
...更聪明地工作,而不是更努力
我已经为数周的时间而苦苦挣扎,寻找在逻辑上和技术上最好的方法,同时尝试以连续、轮换的方式匹配 2 大组文本。
一方面,我们有歌曲及其歌词(大约 3000 万行文本,每行约 1000 个字符),另一方面我们有歌曲歌词类别(约 20K,每行约 50 个字符)。歌词类别指的是歌曲的内容。
每首歌都应该归入一个或多个类别,在我看来,这只能通过比较每个类别中的单词与歌曲歌词的相关性来完成,然后选择全文搜索得分最高的那个(或超过 1 个类别,对于那些得分相同的类别),同时考虑同义词、词干提取、停用词和适当的全文搜索引擎的所有附加功能.如果你有更好的方法来解决这个问题,请不要犹豫给我一个提示。
举个例子,根据歌词,"Unchained Melody"这首歌应该属于:
- 情歌
- 为了我亲爱的,我的爱
- 感到孤独
- 为了我亲爱的,我的爱
它的歌词确实包含了该类别(它的整个路径)中包含的所有这些词,包括它们的变形和同义词,多次,所以这个类别的文本应该与歌曲的文本相比排名很好.
所以问题是可以使用哪种方法将所有这些类别文本与所有这些歌曲文本匹配?
请记住,自然地,如今每天发布数千首歌曲,并且类别不断changing/improving甚至有可能彻底改变。
到目前为止,我已经尝试了以下方法:
SQL 保存类别的 Server 2014,链接到在其全文索引中保存歌词文本的 Sphinx 搜索引擎。基于这些构建的应用程序对单首歌曲文本执行 20K 次查询(即,获取每个类别与歌曲文本的相关性),选择排名最好的结果。这意味着要匹配所有歌曲的 20K * 30M 查询。当然,这在40核机器+256GB RAM上需要很长时间,到那时,有新歌和可能的changed/updated类别结构。
这个很有趣:SQL 包含歌词的 Server 2014,链接到包含类别文本的 Sphinx。为每首歌曲匹配类别的查询是通过将歌曲文本拆分为单词来创建的,在它们之间使用 "OR" 运算符,如果在一行中找到更多单词(包含类别文本和来自的文本),则结果排名更高它的完整路径)。结果:更快,因为每首歌曲只有 1 个大查询才能获得其排名靠前的类别,但仍然不够快,而且准确度稍差。
SQL Server 2014 同时包含歌词和类别,启用全文搜索,同时使用第一种方法(没有 Sphinx,只有 SQL' s FT) 在一组有限的类别上最初是由第二种方法产生的(同样,没有 Sphinx,只有 SQL 的 FT),所有的东西都分成数百个异步批次的工作。所以,它是以上两者的结合。结果:更准确,并赋予它全部的力量,更快一点,但仍然不够我认为可能的。匹配所有歌曲和歌词大约需要3天时间。
如果您有任何其他想法可以尝试,我将不胜感激。我对准确性 (40%) 和速度 (60%) 很感兴趣,我真的觉得有更简单的方法来完成这项工作。
就我个人而言,我可能会坚持使用您的 1。但有两个改进
批量更新,而不是简单地 运行 每个 category/document 组合一个查询。 运行 每个类别一个查询 - 并获得所有文档的结果。更少的大查询。您可以通过一些优化来使这些 'big' 查询更加高效。
Delta Updates,而不是每个周期,只是 运行ning 'full' 进程,周期性地使用一个单独的更小的特定系统。知道如何 运行 更集中更新以避免重复工作的人。例如:
您添加一个新类别,只需 运行 其大查询即可找到该类别的文档。删除的类别只会删除记录。 'edit' 到类别,可以是删除后跟插入。
新文档,也可以是只包含新文档的特殊 sphinx 索引(main+delta 索引系统可能已经提供了!)。然后 运行 针对这个小得多的增量索引对每个类别进行主查询。
- 甚至可以使用 'speculative' 系统来减少您需要 运行 的类别数量。例如,将类别中的所有单词塞入批量 BuildKeyword 调用中。这可以让你返回每个单词的点击率,这样你就可以排除没有匹配项的类别(因此不需要 运行 主查询,对于许多类别)
...更聪明地工作,而不是更努力