自定义评分器Similarity,提高搜索体验
首先说一下lucene对文档的评分规则:
score(q,d) = coord(q,d) · queryNorm(q) · | ∑ | (tf(t in d) · idf(t)2 · t.getBoost() · norm(t,d) ) |
具体可以查看相关文章:http://blog.chenlb.com/2009/08/lucene-scoring-architecture.html
这里先考虑三个因素coord(q,d)与tf(t in d),当查询串中,命中的词越多,coord计算的值则越大,某个词在文档中出现的次数越多则tf的值越大。还有就是norm(t,d),这个主要是文档boost与字段boost的影响。值越大,对整体评分的影响越重。
首先说tf对搜索结果的影响:
这里是在于本站使用的搜索评分开始是默认的评分器的情况下,但发现有些不足之处。因为站内搜索主要是视频的标题与标签。对于一个视频文档来说,标题或者与标签重复的词本身就是无意义的,比如标题为"美女美女美女美女",标签为“美女”,如果让tf 的作用变大,明显示会使得它的评分更大,而其实并不是视频网站想要的效果。因为我们更想让它更加发散,这样,用户的点击率才会高。所以我们应该让所有命中词的文档的tf 不受频率的影响,使其tf=1.0f;如下自定义的评分器
- /**
- * @author yuzhy
- * 实现自已的评分器
- * 文档中重复多少个词不影响分数
- *
- */
- public class MySolrSimilarity extends DefaultSimilarity {
- @Override
- public float tf(float freq) {
- return 1.0f;
- }
- @Override
- public float tf(int freq) {
- return 1.0f;
- }
- }
别小看这段代码 ,因为使用这种评分,对于一个文档来说,一个term在文档出现的频率并不影响,即是不用担心作弊的情况,因为在这方面上他们的分数都是一样的。之前还考虑了对标题与标签的重复字符串的处理,采用后缀树结构来处理公共子串,后来发现这种方法来得更简洁。
因为使用的是solr来作搜索服务来架构,所以首先修改solr默认的Similarity类。在solr 的配置文件schemal.xml,最后中修改或增加:
<similarity class="com.wole.solr.search.MySimilarity"/>
设置为自定义的评分器,重启solr服务后,自定义的评分器就生效了。搜索" 美女"后,不再出现“美女美女美女美女”文档靠前排的效果了。
接着说一下coord的影响:
搜索“htc Incredible S” 三个词,由于没有这完全命中,则使用了宽松规则,即命中一个词也返回进行排序,之前的评分,前几条的结果为:
- <doc>
- <str name="Subject">S.H.E爱而为一的魔力 幕后全纪录</str>
- <str name="tag">she selina hebe ella 爱而为一</str>
- <int name="public_time">1103150000</int>
- <int name="times">370</int>
- <int name="hd">1</int>
- </doc>
- −
- <doc>
- <str name="Subject">1000种死法-S04-01.1024X576.x264</str>
- <str name="tag">1000种死法 </str>
- <int name="public_time">1103140000</int>
- <int name="times">692</int>
- <int name="hd">1</int>
- </doc>
- −
- <doc>
- <str name="Subject">p-s-1</str>
- <str name="tag"> </str>
- <int name="public_time">1103150000</int>
- <int name="times">58</int>
- <int name="hd">1</int>
- </doc>
可以看到,命中的词S 的文档给排到较前,本应该让命中越来的词的文档分数更高,但因为这三个文档在其它方面影响到评分,使得它的最后分数高于命中多个词的文档,而排到最前,所以这样的搜索体验不够好,好的体验应该是让命中的词越多排得越高,所以我首先降低计算norm(t,d)的值。测试调了其权重值,让coord占更大的比例值,效果马上出来更好的,其前三条记录为:
- <doc>
- <str name="Subject">不可思议htc Incredible 对比 apple iphone4</str>
- <str name="tag">Incredible htc apple iphone4 苹果</str>
- <int name="public_time">1009250000</int>
- <int name="times">29758</int>
- <int name="hd">0</int>
- </doc>
- −
- <doc>
- <str name="Subject">不可思议 htc Incredible 比拼 苹果 iphone 3gs</str>
- <str name="tag">不可思议 Incredible htc 苹果 apple</str>
- <int name="public_time">1009250000</int>
- <int name="times">20231</int>
- <int name="hd">0</int>
- </doc>
- −
- <doc>
- <str name="Subject">HTC incredible拆解全过程</str>
- <str name="tag">手机 HTC incredible DROID系列 </str>
- <int name="public_time">1005030000</int>
- <int name="times">3649</int>
- <int name="hd">0</int>
- </doc>
这里命中两个词htc Incredible的文档给排到最前面来,显然这才更符合用户需要的。即使没有完全命中,它的相关性会更逼近。
最后讲一下norm(t,d):
没有norms 意味着
索引阶段禁用了文档boost 和域的boost 及长度标准化。好处在于节省内存,不用在搜索阶
段为索引中的每篇文档的每个域都占用一个字节来保存norms 信息了。但是对norms 信息
的禁用是必须全部域都禁用的,一旦有一个域不禁用,则其他禁用的域也会存放默认的
norms 值。因为为了加快norms 的搜索速度,Lucene 是根据文档号乘以每篇文档的norms
信息所占用的大小来计算偏移量的,中间少一篇文档,偏移量将无法计算。也即norms 信
息要么都保存,要么都不保存。
norm(t,d) 压缩几个索引期间的加权和长度因子:
- Document boost - 文档加权,在索引之前使用 doc.setBoost()
- Field boost - 字段加权,也在索引之前调用 field.setBoost()
- lengthNorm(field) - 由字段内的 Token 的个数来计算此值,字段越短,评分越高,在做索引的时候由 Similarity.lengthNorm 计算。
以上所有因子相乘得出 norm 值,如果文档中有相同的字段,它们的加权也会相乘:
norm(t,d) = doc.getBoost() · lengthNorm(field) · | ∏ | f.getBoost() |
field f in d named as t |
搜索组件为dismax,其中文档bf的计算是由三个字段
public_time (视频发布时间)^15,times(视频播放数)^15,hd(视频高清)^4
字段的bf值为
qf=Subject^1+tag^0.3
如果想让coord的值靠前,计算文档 boost 与字段boost 的值应该降低一个级别。
改为:
public_time (视频发布时间)^1.5,times(视频播放数)^1.5,hd(视频高清)^0.4
这样 norm计算的值就远远小于 coord ,使命中越多词分数越高的效果
norm(t,d) = doc.getBoost() · lengthNorm(field) · | ∏ | f.getBoost() |
field f in d named as t |
转载于:https://www.cnblogs.com/ibook360/archive/2011/11/01/2231511.html
自定义评分器Similarity,提高搜索体验相关推荐
- 自定义评分器Similarity,提高搜索体验(转)
文章转自:http://blog.csdn.net/duck_genuine/article/details/6257540 首先说一下lucene对文档的评分规则: score(q,d) = ...
- 防百度云加速html,国内免费CDN百度云加速服务体验 - 国内外加速、防护、提高搜索体验...
百度云加速从早期与加速乐的合作,到目前独立开发和运营的3.0版本,基本上已经完成功能和结构以及全国大部分节点的布局.目前百度云加速有提供免费/付费国内CDN服务(需要BA)以及免费国外CDN服务(如果 ...
- 从提高 Elasticsearch 搜索体验说开去......
Elasticsearch 最少必要知识实战教程直播回放 1.实战问题 球友提问:怎么搜索才能使得结果是最好的呢? 我这边一个搜索功能,实现做法就是将用ik分词器配合multi查询实现的. 中途也追加 ...
- Elasticsearch 分布式搜索引擎 -- 自动补全(拼音分词器、自定义分词器、自动补全查询、实现搜索框自动补全)
文章目录 1. 自动补全 1.1 拼音分词器 1.2.1 自定义分词器 1.2.2 小结 1.2 自动补全 1.3 实现酒店搜索框自动补全 1.3.1 修改酒店映射结构 1.3.2 修改HotelDo ...
- 星起航:抖音小店体验分低怎么办,如何提高店铺体验评分?
店铺体验分是一个非常重要的因素,它影响着店铺的方方面面.体验评分可以引导老客户的二次转化和新客户的下单.体验评分是顾客评判店铺.产品的标准.如果体验分数低,你给客户的信任就会越来越低,从而影响转化率. ...
- 数据库-Elasticsearch进阶学习笔记(分片、映射、分词器、即时搜索、全文搜索等)
目录 基础概念 定义 特点 索引(Index) 分片(Shards) 副本(Replicas) 分配(Allocation) 映射(Mapping) 动态映射 显式映射 常见数据类型 文档(docum ...
- Elastic App Search:免费的产品,可提供出色的搜索体验
无论人们在何处遇到搜索栏(无论是在Google,手机应用程序上还是在在线购物时),他们都有条件期望能带来快速且相关结果的搜索体验.考虑到这一不断发展的期望,多年来,数百万开发人员和组织选择Elasti ...
- ES自定义评分机制:function_score查询详解
一.function_score介绍 主要用于让用户自定义查询相关性得分,实现精细化控制评分的目的. 在ES的常规查询中,只有参与了匹配查询的字段才会参与记录的相关性得分score的计算.但很多时候我 ...
- 电商搜索“想用户所想,提高搜索结果质量”实践方案
案例背景 国内某头部母婴垂直类电商平台,致力于提供多元的产品和服务,满足中国年轻家庭知识获取.交流交友.记录成长和消费购物的四个核心需求,营收主要来源于商城部分,我们之前提到,大部分垂直类电商搜索转化 ...
最新文章
- 【ZJOI 2008】树的统计 Count
- 进程程序替换(自主实现shell)
- Ethernet IP TCP UDP 协议头部格式
- 计算机程序的构造和解释 python_SICP Python 描述 第三章 计算机程序的构造和解释 3.1 引言...
- 小程序开发之基础知识(0)
- Python3 从零单排7_模块ossys
- Java、JavaScript、C/C++、Python分别用来开发什么?
- 软件测试启航篇:测试的分类
- 模块化配电系统在高密度数据中心的应用
- 数据库,SQL,万恶之源?
- 什么是磁盘列阵技术?
- win10开启显示:你的电脑/设备需要修复,错误代码:0xc0000225
- 浅谈嵌入式MCU软件开发之S32K1xx系列MCU启动过程及重映射代码到RAM中运行方法详解
- 桌面壁纸 Lively wallpape
- idea如何给main函数中的args[] 字符串数组赋值
- Bootstrap 字体图标和自定义矢量图标
- linux访问网页详细过程
- [深度学习][原创]常用ocr框架和技术总结
- C语言中一个程序写完后怎么运行啊?
- 网站漏洞检测服务 URL跳转漏洞的检测与修复
热门文章
- Apache与Tomcat联系及区别
- 找到表中某一列值相同的记录,而且只要其中一条记录的sql
- Win10打不开jar程序的解决方法 [转载]
- 汽车票销售系统mysql,jsp683客运汽车票网上售票系统mysql
- python创建excel图表_python使用VBA(8):Excel创建图表(简单)
- sublime php 乱码,sublime打开TXT文件乱码的问题
- linux中文系统装offci,Ubuntu 14.04 LTS中安装fcitx中文输入法的教程
- oracle10.2 管理工具,Oracle 10.2.0.5 EM管理器的BUG
- mysql query 查询失败_如何在mysql进行查询缓存及失败的解决方法
- redis实现轮询算法_用redis实现支持优先级的消息队列