前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Elasticsearch全文搜索与TF/IDF

Elasticsearch全文搜索与TF/IDF

作者头像
Stanley Sun
发布2019-09-23 15:05:35
1.8K0
发布2019-09-23 15:05:35
举报

一、TF/IDF

1. TF

TF:Term Frequency,即词频。它表示一个词在内容(如某文章)中出现的次数。为了消除文档本身大小的影响,通常,它的定义是:

TF = 某个词在文档中出现的次数 / 文档的总词数

也有其他表示方法,在Elasticsearch (lucene)中的使用的方法是

tf(t in d) = √frequency , 即 (某个词t在文档d中出现的次数) 的 平方跟

某个词出现越多,表示它约重要。比如某篇新闻中,“剑术”出现了5次,“电视”出现了1次,很可能这是一个剑术赛事报道。

如果这篇新闻中,“中国”和“剑术”出现的次数一样多,是不是表示两者同等重要呢?答案是否定的,因为中国这个词很常见,它难以表达文档的特性。而剑术很少见,更能表达文章的特性。

某个词越少见,就越能表达一篇文章的特性,反之则越不能。像“的”、“了”这些词,在所有文档中出现的频率都特别高,以至于失去了表达文章特性的意义。人们干脆称它们为“停用词”,直接从统计中忽略掉。

2. IDF

IDF(Inverse Document Frequency),即逆文档频率,它是一个表达词语重要性的指标。通常,它的计算方法是:

IDF=log(语料库中的文档数/(包含该词的文档数+1))

如果所有文章都包涵某个词,那个词的IDF=log(1)=0, 即重要性为零。停用词的IDF约等于0。

如果某个词只在很少的文章中出现,则IDF很大,其重要性也越高。

为了避免分母为0,所以+1.

在Elasticsearch (lucene)中的计算方法是

idf(t) = 1 + log ( numDocs / (docFreq + 1)) , 即 1 + log ( 索引中的文档总数 / (包含该词的文档数 + 1))

上述公式是文档中给的,但实际中用的是 log(1 + (docCount - docFreq + 0.5) / (docFreq + 0.5))

TF-IDF值

TF-IDF = TF X IDF

在Elasticsearch中,还有一个概念叫 字段长度的归一化,Field-Length Norm.

字段内容越短,权重越大。如果一个关键词出现在较短的字段中,比如title,就比它出现在长字段(如简介)中更能表达文章的特性。

norm(d) = 1 / √numTerms 即: 1 / 词出现次数的平方根

二、elasticsearch的全文搜索

elasticsearh的全文搜索涉及到两个重要的方面:相关性(Relevance)和分析(Analysis)

相关性(Relevance)

它是评价查询与其结果间的相关程度,并根据这种相关程度对结果排名的一种能力,这种计算方式可以是 TF/IDF 方法(参见 相关性的介绍)、地理位置邻近、模糊相似,或其他的某些算法。本文只介绍TF/IDF方法。

TF/IDF 相关性方法分析

做一次搜索,带explain,elasticsearch会返回如何匹配。比如在title字段中进行全文搜索,关键词为'python'

代码语言:javascript
复制
GET course/_search?explain
{
  "query": {
    "multi_match" : {
      "query":    "python",
      "fields": [ "title" ] 
    }
  },"size":10
}

返回内容中,第一条匹配的结果如下

代码语言:javascript
复制
{
        "_shard": "[course][0]",
        ...
        "_score": 6.1884723,
        "_source": {
          "title": "Python 语句",
          ...
        },
        "_explanation": {
          "value": 6.1884723,
          "description": "weight(title:python in 1363) [PerFieldSimilarity], result of:",
          "details": [
            {
              "value": 6.1884723,
              "description": "score(doc=1363,freq=1.0 = termFreq=1.0\n), product of:",
              "details": [
                {
                  "value": 4.4812255,
                  "description": "idf, computed as log(1 + (docCount - docFreq + 0.5) / (docFreq + 0.5)) from:",
                  "details": [
                    {
                      "value": 17,
                      "description": "docFreq",
                      "details": []
                    },
                    {
                      "value": 1545,
                      "description": "docCount",
                      "details": []
                    }
                  ]
                },
                {
                  "value": 1.3809776,
                  "description": "tfNorm, computed as (freq * (k1 + 1)) / (freq + k1 * (1 - b + b * fieldLength / avgFieldLength)) from:",
                  "details": [
                    {
                      "value": 1,
                      "description": "termFreq=1.0",
                      "details": []
                    },
                    {
                      "value": 1.2,
                      "description": "parameter k1",
                      "details": []
                    },
                    {
                      "value": 0.75,
                      "description": "parameter b",
                      "details": []
                    },
                    {
                      "value": 7.861489,
                      "description": "avgFieldLength",
                      "details": []
                    },
                    {
                      "value": 2.56,
                      "description": "fieldLength",
                      "details": []
                    }
                  ]
                }
              ]
            }
          ]
        }
      }
解释
代码语言:javascript
复制
"value": 4.4812255,
"description": "idf, computed as log(1 + (docCount - docFreq + 0.5) / (docFreq + 0.5)) from:",

上面是求idf值的值。idf=ln(1 + (docCount - docFreq + 0.5) / (docFreq + 0.5))=ln(1+(1545-17+0.5)/(17+0.5)) = ln(88.34)=4.4812255

//返回内容里用了log(以10为底的对数), 实际是ln (以e为底的对数)

代码语言:javascript
复制
"value": 1.3809776,
"description": "tfNorm, computed as (freq * (k1 + 1)) / (freq + k1 * (1 - b + b * fieldLength / avgFieldLength)) from:",

上面是求tfNorm(归一化后的TF)的值。根据描述tfNorm = (freq * (k1 + 1)) / (freq + k1 * (1 - b + b * fieldLength / avgFieldLength))

其中termFreq=1,k1=1.2, b=0.75, avgFieldLength=7.861489, fieldLength=2.56。

为什么要用这样的公式,以及k1和b的值是怎么来的,我也不清楚。

计算最终结果,tfNorm=1.38.

代码语言:javascript
复制
"value": 6.1884723,
"description": "score(doc=1363,freq=1.0 = termFreq=1.0\n), product of:",

最终得分 TF-IDF = TF * IDF =4.4812255 * 1.3809776 = 6.1884723

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、TF/IDF
    • 1. TF
      • 2. IDF
      • 二、elasticsearch的全文搜索
        • 相关性(Relevance)
          • TF/IDF 相关性方法分析
            • 解释
        相关产品与服务
        Elasticsearch Service
        腾讯云 Elasticsearch Service(ES)是云端全托管海量数据检索分析服务,拥有高性能自研内核,集成X-Pack。ES 支持通过自治索引、存算分离、集群巡检等特性轻松管理集群,也支持免运维、自动弹性、按需使用的 Serverless 模式。使用 ES 您可以高效构建信息检索、日志分析、运维监控等服务,它独特的向量检索还可助您构建基于语义、图像的AI深度应用。
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档