Elasticsearch 如何实现相似推荐功能?

r660926
发布于 2022-4-20 16:31
浏览
0收藏

Elasticsearch 如何实现相似推荐功能?-鸿蒙开发者社区
拿我们身边的算法“投喂”为主的头条、抖音、微信视频号等举例,如果你喜欢乒乓球,每天推送给你的都是乒乓球比赛视频集锦;如果你喜欢成功人士演讲,每天都是马云、马化腾、刘强东等商业巨鳄的演讲。

 

再拿电商的示例如下:比如我近期购买的吴军老师推荐的科普经典巨著《从一到无穷大》,京东会给我推荐樊登读书带火的书《微积分原理》。

Elasticsearch 如何实现相似推荐功能?-鸿蒙开发者社区

其实,在实际业务实战环节,或多或少也会有类似的功能,Elasticsearch 有没有类似功能呢?


大家实战环节遇到的问题也大致如下:

Elasticsearch 如何实现相似推荐功能?-鸿蒙开发者社区Elasticsearch 如何实现相似推荐功能?-鸿蒙开发者社区
这里不得不介绍:MLT 检索。对!你没看错。不是:MIT(麻省理工学院),是 Elasticsearch 一种检索类型 MLT(More Like This Query )。

 

看下图,建立个全局认识。MLT 属于:Query DSL下的专业检索(Specialized queries)的范畴。

Elasticsearch 如何实现相似推荐功能?-鸿蒙开发者社区

Elasticsearch 如何实现相似推荐功能?-鸿蒙开发者社区
More Like This 检索定义:查找与给定文档“相似”的文档。

 

Elasticsearch 如何实现相似推荐功能?-鸿蒙开发者社区
MLT 查询简单地从输入的待查询文本中提取文本,对其进行分析,通常在字段中使用相同的分析器,然后选择具有最高 tf-idf 的前 K 个词组以形成这些词组的组合查询语句。

 

假设我们想找到与给定输入文档相似的所有文档。显然,输入文档本身应该是该类型查询的最佳匹配。为什么呢?基于 Lucene tf-idf 评分公式计算得出的呀。

如下就是 Lucene tf-idf 评分模型。

Elasticsearch 如何实现相似推荐功能?-鸿蒙开发者社区

如果对此评分不了解的同学,推荐阅读:


干货 | 一步步拆解 Elasticsearch BM25 模型评分细节


实战 | Elasticsearch自定义评分的N种方法


MLT 查询的本质是:从待检索语句中提取文本,然后用分词器切分,选择 tf-idf 分值高的前 K 个术语形成检索语句。基于检索语句返回的结果就是相似度查询结果。

 

为避免歧义,对照的英文如下:

Elasticsearch 如何实现相似推荐功能?-鸿蒙开发者社区
如果原理还不够清晰,我将核心 Lucene 源码的逻辑简要说明如下:

 

 •  步骤 1:根据输入的待查询的文档,抽取词组单元(term),结合TF*IDF 评分形成优先级队列。


抽取词时会过滤掉停用词、不满足最小词频的词等不满足限定条件的词。


 •  步骤 2:结合步骤 1 的优先级队列,生成布尔查询语句。
 Elasticsearch 如何实现相似推荐功能?-鸿蒙开发者社区

Lucene 源码部分截图


循环超过最大查询词数目,则停止构建查询语句。

 

最大查询数据值 max_query_terms 默认是:25。增加此值会以牺牲查询执行速度为代价提供更高的准确性。


 •  步骤 3:基于步骤2构造的布尔查询语句,获取查询结果。


返回结果就是类似推荐功能的相似文章。


看的出来,这比我们常见的精准匹配 term query 和全文检索 match query、match_pharse query 都要复杂很多。


Elasticsearch 如何实现相似推荐功能?-鸿蒙开发者社区
执行 MLT 的字段必须被索引并且类型为 text 或 keyword。此外,当对文档使用相似度检索时,必须启用 _source 或设置为 stored 或存储为 term_vector。为了加快分析速度,可以在索引时存储 terrm vectors。

 

读者看到这里可能会疑惑:啥叫 term vectors ?

 

有必要解释一下:

 

 •  term vectors 组成:

 

 •  terms 分词单元列表。

 

 •  每个分词单元的位置 position  和序号。

 

 •  分词后的单词或字在原有串中的起始位置 start_offset 、结束位置  end_offset 和偏移值。

 

 •  有效载荷。与位置相关的用户定义的二进制值。

 

给了一堆术语,还是看不懂,再来?!

 

给个例子,一看就明白了。

Elasticsearch 如何实现相似推荐功能?-鸿蒙开发者社区

position 更精确的说法是:序号。

 

 •  Quick 的 position 为 0;


 •  brown 的 position 为 1;


 •  quick 的 start_offset 为 0;


 •  quick 的 end_offset 为 5。

 Elasticsearch 如何实现相似推荐功能?-鸿蒙开发者社区
Elasticsearch 如何实现相似推荐功能?-鸿蒙开发者社区
光说不练是假把式,实战一把,一探究竟。

 

插入一批数据,数据来源:百度热点新闻 。

Elasticsearch 如何实现相似推荐功能?-鸿蒙开发者社区

PS:以上仅是百度公开的热点新闻,以此举例相似查询,别无其他用途,特此说明。

 

执行 MLT:

Elasticsearch 如何实现相似推荐功能?-鸿蒙开发者社区

返回结果如下:

Elasticsearch 如何实现相似推荐功能?-鸿蒙开发者社区

以如上截图最后一条数据为例,强调说明一下:注意到一个细节,返回结果只是相似,并没有真正做到语义相关。

 

Elasticsearch 如何实现相似推荐功能?-鸿蒙开发者社区


参数看着很好解释,但着实非常难理解,特此解读如下:

 

 •  "min_doc_freq": 2


最小的文档频率,默认为 5。

 

什么意思呢?

 

就拿上面的示例来说,至少得有两篇文章才可以,不管这两篇文章与输入相关与否。

 

更具体点说,如果bulk 写入仅一篇document,哪怕和标题一致也无法返回结果。

 

 •  "min_term_freq": 1


文档中词组的最低频率,默认是2,低于此频率的会被忽略。

 

什么意思呢?

 

就是待检索语句的其中一个分词单元的词频的最小值。

Elasticsearch 如何实现相似推荐功能?-鸿蒙开发者社区

上面的例子更有说服力。

 

更为具体的说,like部分待检索语句的分词词频要至少有一个 >=2 。

 

更多参数建议参考官方文档,不再赘述。

 

Elasticsearch 如何实现相似推荐功能?-鸿蒙开发者社区
在第 6 部分提及,more like this 并没有实现完全的相关度推荐,出现了“噪音” 数据。

 

所以,实战环节使用 more like this 多半基于燃眉之急。

 

如果想深入的实现相似度推荐,推荐方案:

Elasticsearch 如何实现相似推荐功能?-鸿蒙开发者社区

基于类似 simhash 的方式,给每个文档打上 hash 值,基于海明距离实现相似度推荐。

Elasticsearch 如何实现相似推荐功能?-鸿蒙开发者社区

Elasticsearch 如何实现相似推荐功能?-鸿蒙开发者社区
本文介绍了 Elasticsearch 中实现相似推荐的 More Like This 检索方法、实现原理、案例解读。

 

目的是给大家业务系统实现相似推荐提供了理论和实践支撑。

 

大家实战环节如何实现的相似推荐呢?欢迎留言讨论细节。

分类
收藏
回复
举报
回复
    相关推荐