GoDance分布式搜索引擎项目

目录

    • 前言
    • 一、布尔模型
    • 二、 实用评分函数
      • 1. 查询归一化因子
      • 2. 协调因子
      • 3. TF-IDF
        • 3.1 TF
        • 3.2 IDF
        • 3.3 字段长度归一值BOOST
      • 4. 向量空间模型
          • 具体方案
    • 三、按受欢迎度提升权重
    • 四、实时搜索与相关搜索
    • 五、具体实现方案
      • 1. 布尔模型
      • 2. 评分函数
      • 3. 实时相关搜索

前言

5月6日参加了字节跳动青训营,做的一个GoDance分布式搜索引擎项目,到今天5月7日该交大项目了。从刚开始不知道从哪里入手到后面一直开会一直看资料才基本完成了这个项目,所以总结了一下自己负责的相关度搜索算法模块。

资料:控制相关度 | Elasticsearch: 权威指南 | Elastic

Lucene 实用评分函数:

Lucene(或 Elasticsearch)使用 布尔模型(Boolean model) 查找匹配文档,并用一个名为 实用评分函数(practical scoring function) 的公式来计算相关度。这个公式借鉴了 词频/逆向文档频率(term frequency/inverse document frequency)向量空间模型(vector space model),同时也加入了一些现代的新特性,如协调因子(coordination factor),字段长度归一化(field length normalization),以及词或查询语句权重提升

一、布尔模型

not > and > or

在查询中使用 ANDORNOT (与、或和非)这样的条件来查找匹配的文档

full AND text AND search AND (elasticsearch OR lucene)

会将所有包括词 fulltextsearch ,以及 elasticsearchlucene 的文档作为结果集。

二、 实用评分函数

score(q,d)  =  
            queryNorm(q)  
          · coord(q,d)    
          · ∑ (           
                tf(t in d)   
              · idf(t)²      
              · t.getBoost() 
              · norm(t,d)    
            ) (t in q)    
  1. score(q,d) 是文档 d 与查询 q 的相关度评分.
  2. queryNorm(q)查询归一化 因子 (新)。
  3. coord(q,d)协调 因子 (新)。
  4. 查询 q 中每个词 t 对于文档 d 的权重和。
  5. tf(t in d) 是词 t 在文档 d 中的 词频 。
  6. idf(t) 是词 t 的 逆向文档频率 。
  7. t.getBoost() 是查询中使用的 boost(新),查询时权重提升。
  8. norm(t,d) 是 字段长度归一值 ,与 索引时字段层 boost (如果存在)的和(新)。

1. 查询归一化因子

查询归一因子queryNorm )试图将查询 归一化 ,这样就能将两个不同的查询结果相比较。

这个因子是在查询过程的最前面计算的,具体的计算依赖于具体查询,一个典型的实现如下:

queryNorm = 1 / √sumOfSquaredWeights 

sumOfSquaredWeights 是查询里每个词的 IDF 的平方和。

相同查询归一化因子会被应用到每个文档,不能被更改,总而言之,可以被忽略

尽管查询归一值的目的是为了使查询结果之间能够相互比较,但是它并不十分有效,因为相关度评分 _score 的目的是为了将当前查询的结果进行排序,比较不同查询结果的相关度评分没有太大意义

2. 协调因子

协调因子 coord )可以为那些查询词包含度高的文档提供奖励,文档里出现的查询词越多,它越有机会成为好的匹配结果。

设想查询 quick brown fox ,每个词的权重都是 1.5 。如果没有协调因子,最终评分会是文档里所有词权重的总和。例如:

  • 文档里有 fox → 评分: 1.5
  • 文档里有 quick fox → 评分: 3.0
  • 文档里有 quick brown fox → 评分: 4.5

协调因子将评分与文档里匹配词的数量相乘,然后除以查询里所有词的数量,如果使用协调因子,评分会变成:

  • 文档里有 fox → 评分: 1.5 * 1 / 3 = 0.5
  • 文档里有 quick fox → 评分: 3.0 * 2 / 3 = 2.0
  • 文档里有 quick brown fox → 评分: 4.5 * 3 / 3 = 4.5

协调因子能使包含所有三个词的文档比只包含两个词的文档评分要高出很多。

禁用: 暂不考虑这个功能

在某些高级应用中,将协调功能关闭可能更好。设想正在查找同义词 jumpleaphop 时,并不关心会出现多少个同义词,因为它们都表示相同的意思,实际上,只有其中一个同义词会出现。

这种情况下同义词出现一个与出现三个同义词应当没有差别

当使用同义词的时候(参照: 同义词 ),Lucene 内部是这样的:重写的查询会禁用同义词的协调功能。大多数禁用操作的应用场景是自动处理的,无须为此担心。

同义词 :用户搜索 “美国” 并且期望找到包含 美利坚合众国美国美洲 、或者 美国各州 的文档。 然而,他们不希望搜索到关于 国事 或者 政府机构 的结果。

同义词相关不应该包含在搜索这部分,应当在分词时处理完全

3. TF-IDF

3.1 TF

词在文档中出现的频度是多少?频度越高,权重 越高 。 5 次提到同一词的字段比只提到 1 次的更相关。词频的计算方式如下:

tf(t in d) = frequency / sum

frequency : 词t在文档d中出现的次数

sum : 文档d总词数

t 在文档 d 的词频( tf )是该词在文档中出现次数除以总词个数。

3.2 IDF

词在集合所有文档里出现的频率是多少?频次越高,权重 越低

idf(t) = log ( numDocs / (docFreq + 1)) 

numDocs : 文档总数

docFreq : 词t在几个文档中出现

t 的逆向文档频率( idf )是:索引中文档数量除以所有包含该词的文档数,然后求其对数。

3.3 字段长度归一值BOOST

title应该比content更重要,TITLEBOOST = 2 ,title是content的 TITLEBOOST倍。

在求title与content权重和的时候进行运算

4. 向量空间模型

向量空间模型(vector space model) 提供一种比较多词查询的方式,单个评分代表文档与查询的匹配程度,为了做到这点,这个模型将文档和查询都以 向量(vectors) 的形式表示:

向量实际上就是包含多个数的一维数组,例如:

[1,2,5,22,3,8]

设想如果查询 “happy hippopotamus” ,常见词 happy 的权重较低,不常见词 hippopotamus 权重较高,假设 happy 的权重是 2 , hippopotamus 的权重是 5 ,可以将这个二维向量—— [2,5] ——在坐标系下作条直线,线的起点是 (0,0) 终点是 (2,5) 。

Figure 27. 表示 “happy hippopotamus” 的二维查询向量

在这里插入图片描述

现在,设想我们有三个文档:

  1. I am happy in summer 。
  2. After Christmas I’m a hippopotamus
  3. The happy hippopotamus helped Harry 。

可以为每个文档都创建包括每个查询词—— happyhippopotamus ——权重的向量,然后将这些向量置入同一个坐标系中:

  • 文档 1: (happy,____________) —— [2,0]
  • 文档 2: ( ___ ,hippopotamus) —— [0,5]
  • 文档 3: (happy,hippopotamus) —— [2,5]

在这里插入图片描述

根据夹角的余弦值:文档3 > 文档2 > 文档1

具体方案
  1. Cosine(a []float64, b []float64)
    这个余弦函数可以计算两组一维数组的余弦值
  2. 只需要计算每一个文档中文档的权重,将其带入与关键词的向量值进行余弦值比较(余弦值越大夹角越小),从大到小排序

三、按受欢迎度提升权重

资料:https://www.elastic.co/guide/cn/elasticsearch/guide/current/boosting-by-popularity.html

资料是从点赞方面考虑的,而为了搜索引擎的使用范围考虑,我们考虑他的浏览量

与使用乘积的方式相比,使用评分 _score 与函数值求和的方式可以弱化最终效果,特别是使用一个较小 factor 因子时

new_score = old_score + log(1 + 0.1 * number_of_votes)

Combining popularity with

number_of_votes : 浏览量

参数0.1是根据点赞数得出的,因为浏览量比点赞数大得多,后面可以测试修改出合适的值

四、实时搜索与相关搜索

输入框的词不用进行分词处理,直接使用即可

  1. 存储:创建字典树存储搜索的关键词。

  2. 查询:根据关键词从头搜索字典树,没有更多的词或者词数大于最大词数50(官方推荐)时结束,边搜索边加入小顶堆(个数为10)。

    取出小顶堆的10个词按照大到小数组形式返回结果。

  3. 添加:搜索结束后将搜索词加入到字典树中,字典树会根据用户的搜索行为逐渐增加

实现方案:

  1. 实时搜索 : 输入搜索条件就会自动补全用户想要的内容,当用户多输入一个字符时就得重新查询,所以查询速度要快。

    • 用户输入搜索词后进行实时查询,直接将结果返回,结果集 <= 10
  2. 相关搜索: 搜索后显示相关的内容在页面最下方,跟实时搜索一样的步骤,但只需要查询一次。

    • 用户点击搜索按钮后进行相关查询,如果结果集 <= 10,就将搜索词进行分词,对这些分词分别进行查询添加到结果集中

五、具体实现方案

1. 布尔模型

接口函数:

func DocMergeFilter(docQueryNodes []utils.DocIdNode, docFilterIds []uint64, notDocQueryNodes []utils.DocIdNode) []uint64 

作用:合并去重搜索词和范围查询的文档id,过滤掉过滤词的文档id。

  1. 将搜索词与范围查询词的文档id集合通过升序合并函数merge进行合并.

  2. func merge(nums1 []uint64, nums2 []uint64) []uint64  //升序合并函数
    
  3. 通过map记录需要过滤的文档id(方便快速查找)

  4. NOT:遍历合并后的文档id,如果id在map中存在就删除。

2. 评分函数

接口需要参数:(map[string]int,关键词分词文档, 标题分词单词文档, 内容分词单词文档, 浏览量)

  1. TF-IDF

    • TF() : 在创建索引时计算每一个单词的词频
    • IDF() : 计算每一个单词的逆文件频率
    • TwoWeightSum : 计算标题或者摘要与内容的单词权重和,BOOST控制倍数
  2. Vector

    • VectorCosine() : 计算两组向量余弦值
    • VectorPosition() : 获取所有文档向量
    • KeyVectorPosition() : 获取关键词的向量
    • DocVectorWeight() : 获取所有文档的向量余弦值
  3. Coord

    • CoordAndVectorWeight(): 计算协调因子与向量权重的乘积

步骤:

  1. 遍历搜索词集searchQueries,通过SearchKeyDocIds()方法查询倒排,因为在布尔模型过滤的时候没有修改倒排里的文档,所以此时倒排文档ids有可能包含过滤词文档,在这时候得先过滤掉过滤词文档。

  2. idf : 倒排查出的ids长度就是这个单词出现的文档个数

    idf := math.Log(docNum / float64(len(ids)+1))
    
  3. 遍历ids计算每一个文档单词的TFIDF

  4. 空间向量模型vector :

    • 所有文档向量vectorAllDoc:是一个map[uint64][]float64的类似二维数组结构,计算完TFIDF后直接添加进去
    • 搜索词文档向量vectorKey : 是一个[]float64,每一个单词权重都取这个单词在所有文档中TFIDF的最大值
    • 然后通过weight.DocVectorWeight()方法算两个向量余弦值
  5. 协调因子coord: 该文档中出现的搜索词数 / 总搜索词数

    • 计算coord后将每一篇文档的coord与文档向量权重docVectorWeight相乘得到文档的权重,然后按照权重从大到小排序

3. 实时相关搜索

  1. trie:
    • Insert() : 用于向字典树添加搜索词语
    • Search() : 在字典树中查询搜索词语相关的词语返回
      • 如果参数BOOT = true代表实时搜索,返回<=10条数据
      • 如果参数BOOT = true代表相关搜索,返回10条数据,不够时用words补全
  2. heap:
    • 小顶堆:根据词语频次大小进行排序,相等就根据词语长短进行排序,总的就是越小越长越靠近堆顶,堆大小为10,超过就弹出堆顶,保证剩下的都是频次越长单词越短的数据
    • 服务于trie的一个中间容器
  3. queue:
    • 用数组实现队列,在trie/Search()方法中使用到广搜时使用
    • 结构体中除了存 []*Trie节点,还存了 [] []rune,用于存储这个节点的整体词语
    • Add(): 在添加过程中除了添加Trie节点,还要添加rune的一个节点单词数据,用于记录整个词语
    • Remove() : 弹出队列头:(*Trie, []rune)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/270067.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

<script setup> 的作用

一、使用<script setup> 之后&#xff0c;就不需要手动写以下代码&#xff0c;只要写逻辑代码 未加setup&#xff0c;vite 工程要加上下面代码 *export default{ * setup(){ * //只要写逻辑代码 * return{***} * } * } 加了setup &#xff0c;export default 、…

doris基本操作,05-Rollup

简述 Rollup类似于mysql的视图&#xff0c;区别在于视图并没有将数据独立存储&#xff0c;视图是逻辑上的连接。而Rollup将数据独立存储了&#xff0c;玩的是真的。当查询命中Rollup时&#xff0c;会从Rollup表里获取数据&#xff0c;提高查询效率。 操作 创建Rollup表 alt…

web自动化测试的智能革命:AI如何推动软件质量保证的未来

首先这个标题不是我取的&#xff0c;是我喂了关键字让AI给取的&#xff0c;果然非常的标题党&#xff0c;让人印象深刻&#xff0c;另外题图也是AI自动生成的。 先简单回顾一下web自动化测试的一些发展阶段 QTP时代 很多年前QTP横空出世的时候&#xff0c;没有人会怀疑这种工…

插入排序详解(C语言)

前言 插入排序是一种简单直观的排序算法&#xff0c;在小规模数据排序或部分有序的情况下插入排序的表现十分良好&#xff0c;今天我将带大家学习插入排序的使用。let’s go ! ! ! 插入排序 插入排序的基本思想是将待排序的序列分为已排序和未排序两部分。初始时&#xff0c…

【序列化和反序列化】

&#x1f341;什么是序列化和反序列化&#xff1f; &#x1f341;典型解析&#x1f341;拓展知识仓&#x1f341;如何进行序列化和反序列化&#x1f341;未实现Serializable&#xff0c;可以序列化吗? &#x1f341;典型解析 在Java中&#xff0c;我们可以通过多种方式来创建对…

java接口限流详解

目录 1.简介1.1.为什么需要限流?1.2.限流和熔断有什么区别&#xff1f;1.3.限流和削峰有什么区别&#xff1f;1.4 缓存&#xff0c;降级&#xff0c;限流简介 2.应用级限流2.1 控制并发数量2.2 控制访问速率2.2.1 令牌桶算法2.2.2 漏桶算法 3.分布式限流4.交流群 1.简介 接口…

渗透测试——1.3计算机网络基础

一、黑客术语 1、肉鸡&#xff1a;被黑客攻击电脑&#xff0c;可以受黑客控制不被发现 2、端口&#xff08;port&#xff09;&#xff1a;数据传输的通道 3、弱口令&#xff1a;强度不高&#xff0c;容易被猜到的口令、密码 4、客户端&#xff1a;请求申请电脑&#xff08;…

宝塔mysql本地服务器状态异常如何解决

今天安装宝塔的时候突然遇到的问题 来吧 直接上bug图 答案&#xff1a;修改Mysql数据库密码

【论文阅读笔记】SegVol: Universal and Interactive Volumetric Medical Image Segmentation

Du Y, Bai F, Huang T, et al. SegVol: Universal and Interactive Volumetric Medical Image Segmentation[J]. arXiv preprint arXiv:2311.13385, 2023.[代码开源] 【论文概述】 本文思路借鉴于自然图像分割领域的SAM&#xff0c;介绍了一种名为SegVol的先进医学图像分割模型…

不同参数规模大语言模型在不同微调方法下所需要的显存总结

原文来自DataLearnerAI官方网站&#xff1a; 不同参数规模大语言模型在不同微调方法下所需要的显存总结 | 数据学习者官方网站(Datalearner)https://www.datalearner.com/blog/1051703254378255 大模型的微调是当前很多人都在做的事情。微调可以让大语言模型适应特定领域的任…

JY901S 9轴姿态角度传感器模块

JY901S 9轴姿态角度传感器模块 JY901S 简介模块特性引脚说明IIC通讯IIC读写寄存器代码示例 JY901S 简介 模块集成高精度的陀螺仪、加速度计、地磁场传感器&#xff0c;采用高性能的微处理器和先进的动力学解算与卡尔曼动态滤波算法&#xff0c;能够快速求解出模块当前的实时运…

【K8S基础】-k8s的核心概念控制器和调度器

Kubernetes是一个开源的容器编排平台&#xff0c;旨在简化和自动化容器化应用程序的部署、扩展和管理。它提供了一个强大的基础设施来管理容器化应用程序的生命周期&#xff0c;并确保它们在整个集群中高效运行。 Kubernetes的核心概念包括集群、节点、Pod、控制器、调度器等。…

360压缩安装一半不动了怎么办?

360压缩软件是我们常用的压缩软件&#xff0c;但是常常会遇到压缩安装到一半停止的情况&#xff0c;下面提供了一些可能的原因和解决办法&#xff0c;大家可以进行尝试~ 方法一&#xff1a;关闭防火墙和杀毒软件 有时候&#xff0c;防火墙和杀毒软件可能会阻止360压缩的安装过…

使用ArcMap进行实测数据处理

文章目录 题目流程 题目 实验名称&#xff1a;实测数据处理 实验目的及要求&#xff1a; 1. 掌握实测点数据转为矢量点数据方法 2. 掌握数据投影变换方法 3. 掌握点数据插值方法 流程 1&#xff0c;打开ArcMap软件&#xff0c;在左菜单栏上选中File&#xff0c;然后鼠标移…

电脑开机快捷启动,启动菜单没有u盘怎么办

电脑开机快捷启动键找不到u盘怎么办 对于快捷启动键找不到u盘的问题&#xff0c;小编很了解其中的门道&#xff0c;因为开机找不到u盘是我们使用电脑时候的常见问题。那么我们到底要如何解决开机找不到u盘的问题呢?其实方法还是蛮简单的&#xff0c;下面小编就来教大家电脑开…

Maven高级篇

Maven依赖管理原则; 可选依赖&#xff1a;隐藏当前项目中的指定的包&#xff0c;如此&#xff0c;别的包引用当前包时&#xff0c;当前包中的指定包就被隐藏了&#xff0c;在别的包中无法看到隐藏的包 排除依赖&#xff1a;指定排除引用包中所包含的依赖&#xff0c;防止与当…

解决 Solidworks2021 报错(-15,10032,0)错误记录

Solidworks2021 报错"-15,10032,0"错误记录 如图所示解决方案步骤1步骤2 个人问题我的没法添加白名单&#xff0c;要是有能解决的大神给个解决方式感激不尽&#xff01;&#xff01; 如图所示 解决方案 步骤1 该问题的解决方式仅对个人有效&#xff0c;不一定通用&…

MY FILE SERVER: 1

下载地址 https://download.vulnhub.com/myfileserver/My_file_server_1.ova 首先我们需要发现ip 我的kali是59.162所以167就是靶机的 然后我们拿nmap扫一下端口 nmap -sV -p- 192.168.59.167 扫完发现有七个端口开放 按照习惯先看80 没看到有啥有用信息,用nikto扫一下 nik…

[环境配置]win11关闭病毒和威胁防护防止乱删软件

选择桌面的开始图标&#xff0c;选择“设置”功能 点击隐私和安全性功能&#xff0c;进入“Windows安全中心” 点击开启Windows安全中心。 将实时保护和其他保护功能进行关闭就可以了。

jQuery实现layer.open中按钮倒计时读秒可用的协议阅读场景

今日遇到一个系统注册页网站 条款签接受流程改动的需求&#xff0c;往日多是使用他人网站注册登录&#xff0c;看见相关协议的授权设计大同小样&#xff0c;觉得挺有意思&#xff0c;这次遇到了需要我来实现这个功能&#xff0c;但是用习惯了vue的封装&#xff0c;这次是依靠jQ…