位置: 编程技术 - 正文

对JavaScript的全文搜索实现相关度评分的功能的方法(javascript的对象有哪些)

编辑:rootadmin

推荐整理分享对JavaScript的全文搜索实现相关度评分的功能的方法(javascript的对象有哪些),希望有所帮助,仅作参考,欢迎阅读内容。

文章相关热门搜索词:javascript的对象,说明javascript的作用,说明javascript的作用,javascript的对象有哪些,javascript的描述,javascript的语句,javascript的语句,说明javascript的作用,内容如对您有帮助,希望把文章链接给更多的朋友!

全文搜索,与机器学习领域其他大多数问题不同,是一个 Web 程序员在日常工作中经常遇到的问题。客户可能要求你在某个地方提供一个搜索框,然后你会写一个类似 WHERE title LIKE %:query% 的 SQL 语句实现搜索功能。一开始,这是没问题,直到有一天,客户找到你跟你说,“搜索出错啦!”

当然,实际上搜索并没有“出错”,只是搜索的结果并不是客户想要的。一般的用户并不清楚如何做精确匹配,所以得到的搜索结果质量很差。为了解决问题,你决定使用全文搜索。经过一阵枯燥的学习,你开启了 MySQL 的 FULLTEXT 索引,并使用了更高级的查询语法,如 “MATCH() … AGAINST()” 。

好了,问题解决,完结撒花!数据库规模不大的时候是没问题了。

但是当你的数据越来越多时,你会发现你的数据库也越来越慢了。MySQL 不是一个非常好用的全文搜索工具。所以你决定使用 ElasticSearch,重构代码,并部署 Lucene 驱动的全文搜索集群。你会发现它工作的非常好,又快又准确。

这时你不禁会想:为什么 Lucene 这么牛逼呢?

本篇文章(主要介绍 TF-IDF,Okapi BM- 和普通的相关性评分 )和 下一篇文章 (主要介绍索引)将为你讲述全文搜索背后的基本概念。

相关性

对每一个搜索查询,我们很容易给每个文档定义一个“相关分数”。当用户进行搜索时,我们可以使用相关分数进行排序而不是使用文档出现时间来进行排序。这样,最相关的文档将排在第一个,无论它是多久之前创建的(当然,有的时候和文档的创建时间也是有关的)。

有很多很多种计算文字之间相关性的方法,但是我们要从最简单的、基于统计的方法说起。这种方法不需要理解语言本身,而是通过统计词语的使用、匹配和基于文档中特有词的普及率的权重等情况来决定“相关分数”。

这个算法不关心词语是名词还是动词,也不关心词语的意义。它唯一关心的是哪些是常用词,那些是稀有词。如果一个搜索语句中包括常用词和稀有词,你最好让包含稀有词的文档的评分高一些,同时降低常用词的权重。

这个算法被称为Okapi BM。它包含两个基本概念 词语频率(term frequency) 简称词频(“TF”) 和 文档频率倒数(inverse document frequency) 简写为(“IDF”). 把它们放到一起,被称为 “TF-IDF”,这是一种统计学测度,用来表示一个词语 (term) 在文档中有多重要。

TF-IDF

词语频率( Term Frequency), 简称 “TF”, 是一个很简单的度量标准:一个特定的词语在文档出现的次数。你可以把这个值除以该文档中词语的总数,得到一个分数。例如文档中有 个词, ‘the' 这个词出现了 8 次,那么 'the' 的 TF 为 8 或 8/ 或 8%(取决于你想怎么表示它)。

逆向文件频率(Inverse Document Frequency), 简称 “IDF”,要复杂一些:一个词越稀有,这个值越高。它由总文件数目除以包含该词语之文件的数目,再将得到的商取对数得到。越是稀有的词,越会产生高的 “IDF”。

如果你将这两个数字乘到一起 (TF*IDF), 你将会得到一个词语在文档中的权重。“权重”的定义是:这个词有多稀有并且在文档中出现的多么频繁?

你可以将这个概念用于文档的搜索查询。在查询中的对于查询中的每个关键字,计算他们的 TF-IDF 分数,并把它们相加。得分最高的就是与查询语句最符合的文档。

很酷吧!

Okapi BM

上述算法是一个可用的算法,但并不太完美。它给出了一个基于统计学的相关分数算法,我们还可以进一步改进它。

对JavaScript的全文搜索实现相关度评分的功能的方法(javascript的对象有哪些)

Okapi BM 是到目前为止被认为最先进的排名算法之一(所以被称为 ElasticSearch )。Okapi BM 在 TF-IDF 的基础上增加了两个可调参数,k1 和 b,, 分别代表 “词语频率饱和度(term frequency saturation)” 和 “字段长度规约”。这是什么鬼?

为了能直观的理解“词语频率饱和度”,请想象两篇差不多长度的讨论棒球的文章。另外,我们假设所有文档(除去这两篇)并没有多少与棒球相关的内容,因此 “棒球” 这个词将具有很高的 IDF - 它极稀少而且很重要。 这两篇文章都是讨论棒球的,而且都花了大量的篇幅讨论它,但是其中一篇比另一篇更多的使用了“棒球”这个词。那么在这种情况,是否一篇文章真的要比另一篇文章相差很多的分数呢?既然两个两个文档都是大篇幅讨论棒球的,那么“棒球”这个词出现 次还是 次都是一样的。事实上, 次就该封顶啦!

这就是 “词语频率饱和度。原生的 TF-IDF 算法没有饱和的概念,所以出现 次“棒球”的文档要比出现 次的得分高一倍。有些时候,这时我们所希望的,但有些时候我们并不希望这样。

此外,Okapi BM 还有个 k1 参数,它用于调节饱和度变化的速率。k1 参数的值一般介于 1.2 到 2.0 之间。数值越低则饱和的过程越快速。(意味着两个上面两个文档有相同的分数,因为他们都包含大量的“棒球”这个词语)

字段长度归约(Field-length normalization)将文档的长度归约化到全部文档的平均长度上。这对于单字段集合(single-field collections)(例如 ours)很有用,可以将不同长度的文档统一到相同的比较条件上。对于双字段集合(例如 “title” 和 "body")更加有意义,它同样可以将 title 和 body 字段统一到相同的比较条件上。字段长度归约用 b 来表示,它的值在 0 和 1 之间,1 意味着全部归约化,0 则不进行归约化。

算法

在Okapi BM 维基百科中你可以了解Okapi算法的公式。既然都知道了式子中的每一项是什么,这肯定是很容易地就理解了。所以我们就不提公式,直接进入代码:

我们定义了一个简单的静态方法Tokenize(),目的是为了解析字符串到tokens的数组中。就这样,我们小写所有的tokens(为了减少熵)。我们运行Porter Stemmer 算法来减少熵的量同时也提高匹配程度(“walking”和"walk"匹配是相同的)。而且我们也过滤掉停用词(很普通的词)为了更近一步减少熵值。在我所写的概念深入之前,如果我过于解释这一节就请多担待。

这就是addDocument()这种方法会奇迹般出现的地方。我们基本上建立和维护两个类似的数据结构:this.documents.和this.terms。

this.documentsis 是一个保存着所有文档的数据库,它保存着文档的全部原始文字,文档的长度信息和一个列表,列表里面保存着文档中的所有词语和词语的数量与出现频率。使用这个数据结构,我们可以很容易的和快速的(是的,非常快速,只需要时间复杂度为O(1)的哈表查询时间)回答如下问题:在文档 #3 中,'walk' 这个词语出现了多少次?

我们在还使用了另一个数据结构,this.terms。它表示语料库中的所有词语。通过这个数据结构,我们可以在O(1)时间内回答如下问题:'walk' 这个词在多少个文档中出现过?他们的 id 是什么?

最后,我们记录了每个文档的长度,并记录了整个语料库中文档的平均长度。

注意,上面的代码中, idf 被初始化 0,而且 updateidf() 方法被注释掉了。这是因为这个方法运行的非常慢,并且只需在建立索引之后运行一次就可以了。既然运行一次就能满足需求,就没有必要运行次。先把它注释掉,然后在大批量的索引操作之后运行,就可以节省很多时间。下面是这个函数的代码:

这是一个非常简单的函数,但是由于它需要遍历整个语料库中的所有词语,并更新所有词语的值,这就导致它工作的就有点慢。这个方法的实现采用了逆向文档频率 (inverse document frequency) 的标准公式(你可以在 Wikipedia 上找到这个公式)— 由总文件数目除以包含该词语之文件的数目,再将得到的商取对数得到。我做了一些修改,让返回值一直大于0。

最后,search() 方法遍历所有的文档,并给出每个文档的 BM 分数,然后按照由大到小的顺序进行排序。当然了,在搜索过程中遍历语料库中的每个文档实是不明智。这个问题在 Part Two (反向索引和性能)中得到解决。

上面的代码已经做了很好的注释,其要点如下:为每个文档和每个词语计算 BM 分数。词语的 idf 分数已经预先计算好了,使用的时候只需要查询即可。词语频率作为文档属性的一部分也已经预先计算好了。之后只需要简单的四则运算即可。最后给每个文档增加一个临时变量 _score,然后根据 score 做降序排列并返回前 个结果。示例,源代码,注意事项和下一步计划

上面的示例有很多方法进行优化,我们将在 “全文搜索”的第二部分中介绍它们,欢迎继续收看。我希望我能在几个星期之后完成它。下面列了下次将要提到的内容:

反向索引和快速搜索 快速索引 更好的搜索结果

为了这个演示,我编了一个小的维基百科爬虫,爬到相当多()维基百科文章的第一段。由于索引到所有K文件需要秒左右,在我的电脑我已经削减了一半。不想让你们仅仅为了一个简单的全文本演示浪费你的笔记本电脑电量。

因为索引是一个繁重的、模块化的CPU操作,我把它当成一个网络工作者。索引运行在一个后台线程上--在这里你可以找到完整的源代码。你也会发现到词干算法和我的停用词列表中的源代码参考。至于代码许可,还是一如既往为教育目的而免费,而不用于任何商业目的。

最后是演示。一旦索引完成,尝试寻找随机的东西和短语,维基百科会知道的。注意,只有段的索引,所以你可能要尝试一些新的话题。

JavaScript中的Promise使用详解 许多的语言,为了将异步模式处理得更像平常的顺序,都包含一种有趣的方案库,它们被称之为promises,deferreds,或者futures。JavaScript的promises,可以促

JavaScript面对国际化编程时的一些建议 什么是国际化?国际化(Internationalization的缩写是in——i,中间个字符,n)是将软件处理的能让来自各种地方使用各种语言的用户更简单使用的一个过

对JavaScript客户端应用编程的一些建议 你可能注意到了,最近的一段时间越来越多的Web应用有变复杂的趋势,重心从服务端慢慢向着客户端转移。这是个正常的趋势么?我不知道。支持和反

标签: javascript的对象有哪些

本文链接地址:https://www.jiuchutong.com/biancheng/380454.html 转载请保留说明!

上一篇:在JavaScript的AngularJS库中进行单元测试的方法(在javascript中)

下一篇:JavaScript中的Promise使用详解(JavaScript中的数据类型)

  • 一般纳税人财务要求
  • 税务ukey使用教程视频
  • 营改增之前的工程造价怎么算
  • 企业工程款发票税率是多少2021
  • 技术转让所得的税收优惠
  • 合同印花税申报表怎么填写
  • 新个税年终奖怎么申报
  • 股东垫付工资如何做账
  • 简易征收红冲报税方式是什么?
  • 代发工资超过5000 可以不交税吗
  • 印花税的计税依据含税吗
  • 不征税的政府补助如何开票
  • 个人抬头的医药费可以进费用吗
  • 广告服务差额征税
  • 委托销售的增值税税率
  • 电子发票已缴税怎么查
  • 外企投资应该怎么投资
  • 收取对方损失赔偿
  • 税收征收管理权是什么
  • 职工教育经费的扣除限额
  • 折价购入对投资者而言,是为以后多得利息
  • 企业所得税汇算清缴扣除标准2023
  • 零申报 社保
  • 如何开启系统设置
  • php内存占用
  • 实例讲解yii2.0在php命令行中运行的步骤
  • kali linux怎么修改用户名
  • vite中文网
  • 来料加工 增值税
  • php代码生成
  • viwer.js
  • 新必应申请使用资格
  • 针对多用户实现什么功能
  • 公司注册资金减资要交税吗
  • 如何做进项税额明细表
  • centos8 mongodb
  • 软件使用权怎么入账
  • 差旅费报销金额大于实际发生金额
  • 采购流程内容
  • 跨年的房租费用怎么做账
  • 无形资产摊销计算方法
  • 商业企业如何建账
  • 预期损失el
  • 收取物业费如何纳税
  • 制造费用怎么写
  • 不需要计提折旧的情况
  • 期初调整分录
  • 公司报销给个人的会计分录
  • 总公司可以开发票给分公司吗
  • 固定资产转让开票大类是什么
  • 零申报资产负债表填0合适吗
  • 应付账款暂估可以法人付款吗
  • 如何设计高效合理的未来课程
  • sql server数据库查询语句
  • 在windows操作中
  • centosip配置
  • windows蓝屏代码大全及解决方案
  • lol进入游戏后电脑没声音
  • winxp教程
  • win7系统怎么看wi-fi密码
  • win8电脑d盘不见了怎么恢复
  • linux 卸载 mysql
  • win10每周更新
  • win7系统安装谷歌浏览器
  • Linux系统如何创建目录
  • js动态表单
  • python函数enumerate
  • bootstrap技术
  • iframe嵌入页面出现跨域问题
  • python生成器有几种写法
  • Node.js中的什么模块是用于处理文件和目录的
  • shell中的grep怎么用
  • angularjs1.5
  • python 系统日期
  • js复制字符串的方法
  • android开发框架mvp
  • 东营市税务局领导分工
  • 广东发票开票软件
  • 水电费的增值税专用税可抵扣进项
  • 7月税务征收期
  • 免责声明:网站部分图片文字素材来源于网络,如有侵权,请及时告知,我们会第一时间删除,谢谢! 邮箱:opceo@qq.com

    鄂ICP备2023003026号

    网站地图: 企业信息 工商信息 财税知识 网络常识 编程技术

    友情链接: 武汉网站建设