排名评估 API

编辑

允许您评估一组典型搜索查询中排名搜索结果的质量。

请求

编辑

GET /<目标>/_rank_eval

POST /<目标>/_rank_eval

先决条件

编辑
  • 如果启用了 Elasticsearch 安全功能,您必须具有目标数据流、索引或别名的 read 索引权限

描述

编辑

排名评估 API 允许您评估一组典型搜索查询中排名搜索结果的质量。给定这组查询和一组手动评分的文档,_rank_eval 端点会计算并返回典型的信息检索指标,例如平均倒数排名精度折扣累积增益

搜索质量评估首先要查看您的搜索应用程序的用户,以及他们正在搜索的内容。用户有特定的信息需求;例如,他们正在网店中寻找礼物或想预订下次假期的航班。他们通常会在搜索框或其他 Web 表单中输入一些搜索词。所有这些信息,以及关于用户的元信息(例如浏览器、位置、早期偏好等)随后都会转换为对底层搜索系统的查询。

搜索工程师面临的挑战是调整从用户输入到具体查询的转换过程,使其搜索结果包含与用户的信息需求最相关的信息。只有在代表性典型用户查询的测试套件中不断评估搜索结果质量时,才能实现这一点,从而使一个特定查询的排名改进不会对其他类型查询的排名产生负面影响。

为了开始搜索质量评估,您需要三个基本要素

  1. 一组您要评估查询性能的文档,通常是一个或多个数据流或索引。
  2. 一组用户输入到您系统中的典型搜索请求。
  3. 一组文档评级,表示文档与搜索请求的相关性。

请务必注意,每个测试查询都需要一组文档评级,并且相关性判断基于输入查询的用户的信��需求。

排名评估 API 提供了一种方便的方式,可以在排名评估请求中使用此信息来计算不同的搜索评估指标。这使您可以初步估计整体搜索质量,以及在微调应用程序中查询生成的各个方面时可以进行优化的衡量标准。

路径参数

编辑
<目标>
(可选,字符串) 用于限制请求的以逗号分隔的数据流、索引和别名列表。支持通配符 (*)。要定位所有数据流和索引,请省略此参数或使用 *_all

查询参数

编辑
allow_no_indices

(可选,布尔值) 如果为 false,则当任何通配符表达式、索引别名_all 值仅定位到缺失或关闭的索引时,请求将返回错误。即使请求定位到其他打开的索引,此行为也适用。例如,如果索引以 foo 开头,但没有索引以 bar 开头,则定位到 foo*,bar* 的请求将返回错误。

默认为 true

expand_wildcards

(可选,字符串) 通配符模式可以匹配的索引类型。如果请求可以定位数据流,则此参数确定通配符表达式是否匹配隐藏的数据流。支持以逗号分隔的值,例如 open,hidden。有效值包括

all
匹配任何数据流或索引,包括隐藏的数据流或索引。
open
匹配打开的、非隐藏的索引。也匹配任何非隐藏的数据流。
closed
匹配关闭的、非隐藏的索引。也匹配任何非隐藏的数据流。数据流不能关闭。
hidden
匹配隐藏的数据流和隐藏的索引。必须与 openclosed 或两者组合使用。
none
不接受通配符模式。

默认为 open

ignore_unavailable
(可选,布尔值) 如果为 false,则当请求定位到缺失或关闭的索引时,将返回错误。默认为 false

示例

编辑

在最基本的形式中,对 _rank_eval 端点的请求具有两个部分

GET /my-index-000001/_rank_eval
{
  "requests": [ ... ],                            
  "metric": {                                     
    "mean_reciprocal_rank": { ... }               
  }
}

一组典型的搜索请求,以及它们提供的评级

要计算的评估指标的定义

一个特定的指标及其参数

请求部分包含您应用程序典型的多个搜索请求,以及每个特定搜索请求的文档评级。

GET /my-index-000001/_rank_eval
{
  "requests": [
    {
      "id": "amsterdam_query",                                  
      "request": {                                              
          "query": { "match": { "text": "amsterdam" } }
      },
      "ratings": [                                              
        { "_index": "my-index-000001", "_id": "doc1", "rating": 0 },
        { "_index": "my-index-000001", "_id": "doc2", "rating": 3 },
        { "_index": "my-index-000001", "_id": "doc3", "rating": 1 }
      ]
    },
    {
      "id": "berlin_query",
      "request": {
        "query": { "match": { "text": "berlin" } }
      },
      "ratings": [
        { "_index": "my-index-000001", "_id": "doc1", "rating": 1 }
      ]
    }
  ]
}

搜索请求的 ID,用于稍后对结果详细信息进行分组。

要评估的查询。

文档评级列表。每个条目都包含以下参数

  • _index:文档的索引。对于数据流,这应该是文档的后备索引。
  • _id:文档 ID。
  • rating:文档在此搜索请求中的相关性。

文档 rating 可以是任何整数值,表示文档在用户定义的尺度上的相关性。对于某些指标,只需给出二进制评级(例如,不相关的 0 和相关的 1)就足够了,而其他指标可以使用更精细的尺度。

基于模板的排名评估

编辑

作为必须为每个测试请求提供单个查询的替代方法,可以在评估请求中指定查询模板,并在以后引用它们。这样,结构相似、仅参数不同的查询不必在 requests 部分中重复出现。在典型的搜索系统中,用户输入通常会填充到一小组查询模板中,这有助于使评估请求更加简洁。

GET /my-index-000001/_rank_eval
{
   [...]
  "templates": [
     {
        "id": "match_one_field_query",  
        "template": { 
            "inline": {
                "query": {
                  "match": { "{{field}}": { "query": "{{query_string}}" }}
                }
            }
        }
     }
  ],
  "requests": [
      {
         "id": "amsterdam_query",
         "ratings": [ ... ],
         "template_id": "match_one_field_query", 
         "params": { 
            "query_string": "amsterdam",
            "field": "text"
          }
     },
    [...]
}

模板 ID

要使用的模板定义

对先前定义的模板的引用

用于填充模板的参数

您还可以使用 存储的搜索模板

GET /my_index/_rank_eval
{
   [...]
  "templates": [
     {
        "id": "match_one_field_query",  
        "template": { 
            "id": "match_one_field_query"
        }
     }
  ],
  "requests": [...]
}

用于请求的模板 ID

存储在集群状态中的模板 ID

可用评估指标

编辑

metric 部分确定将使用哪些可用评估指标。支持以下指标

K 精度 (P@k)
编辑

此指标衡量前 k 个搜索结果中相关结果的比例。它是著名的 精度指标的一种形式,仅查看前 k 个文档。它是前 k 个结果中相关文档的比例。P@10 的精度值为 0.6 表示前 10 个结果中有 6 个与用户的信息需求相关。

P@k 作为一种简单的评估指标效果良好,优点是易于理解和解释。集合中的文档需要根据当前查询评为相关或不相关。P@k 是一种基于集合的指标,不考虑相关文档在前 k 个结果中的位置,因此包含位置 10 中一个相关结果的十个结果的排名与包含位置 1 中一个相关结果的十个结果的排名一样好。

resp = client.rank_eval(
    index="my-index-000001",
    requests=[
        {
            "id": "JFK query",
            "request": {
                "query": {
                    "match_all": {}
                }
            },
            "ratings": []
        }
    ],
    metric={
        "precision": {
            "k": 20,
            "relevant_rating_threshold": 1,
            "ignore_unlabeled": False
        }
    },
)
print(resp)
response = client.rank_eval(
  index: 'my-index-000001',
  body: {
    requests: [
      {
        id: 'JFK query',
        request: {
          query: {
            match_all: {}
          }
        },
        ratings: []
      }
    ],
    metric: {
      precision: {
        k: 20,
        relevant_rating_threshold: 1,
        ignore_unlabeled: false
      }
    }
  }
)
puts response
const response = await client.rankEval({
  index: "my-index-000001",
  requests: [
    {
      id: "JFK query",
      request: {
        query: {
          match_all: {},
        },
      },
      ratings: [],
    },
  ],
  metric: {
    precision: {
      k: 20,
      relevant_rating_threshold: 1,
      ignore_unlabeled: false,
    },
  },
});
console.log(response);
GET /my-index-000001/_rank_eval
{
  "requests": [
    {
      "id": "JFK query",
      "request": { "query": { "match_all": {} } },
      "ratings": []
    } ],
  "metric": {
    "precision": {
      "k": 20,
      "relevant_rating_threshold": 1,
      "ignore_unlabeled": false
    }
  }
}

precision 指标采用以下可选参数

参数 描述

k

设置每个查询检索的最大文档数。此值将代替查询中常用的 size 参数。默认为 10。

relevant_rating_threshold

设置文档被视为“相关”的评分阈值。默认为 1

ignore_unlabeled

控制如何计算搜索结果中未标记的文档。如果设置为 *true*,则忽略未标记的文档,既不算作相关,也不算作不相关。如果设置为 *false*(默认值),则将其视为不相关。

K 召回率 (R@k)
编辑

此指标衡量前 k 个搜索结果中相关结果的总数。它是著名的 召回率指标的一种形式。它是前 k 个结果中相关文档相对于所有可能相关结果的比例。R@10 的召回率值为 0.5 表示在前 10 个结果中检索到了 8 个相关文档中的 4 个(相对于用户的信息需求)。

R@k 作为一种简单的评估指标效果良好,优点是易于理解和解释。集合中的文档需要根据当前查询评为相关或不相关。R@k 是一种基于集合的指标,不考虑相关文档在前 k 个结果中的位置,因此包含位置 10 中一个相关结果的十个结果的排名与包含位置 1 中一个相关结果的十个结果的排名一样好。

resp = client.rank_eval(
    index="my-index-000001",
    requests=[
        {
            "id": "JFK query",
            "request": {
                "query": {
                    "match_all": {}
                }
            },
            "ratings": []
        }
    ],
    metric={
        "recall": {
            "k": 20,
            "relevant_rating_threshold": 1
        }
    },
)
print(resp)
response = client.rank_eval(
  index: 'my-index-000001',
  body: {
    requests: [
      {
        id: 'JFK query',
        request: {
          query: {
            match_all: {}
          }
        },
        ratings: []
      }
    ],
    metric: {
      recall: {
        k: 20,
        relevant_rating_threshold: 1
      }
    }
  }
)
puts response
const response = await client.rankEval({
  index: "my-index-000001",
  requests: [
    {
      id: "JFK query",
      request: {
        query: {
          match_all: {},
        },
      },
      ratings: [],
    },
  ],
  metric: {
    recall: {
      k: 20,
      relevant_rating_threshold: 1,
    },
  },
});
console.log(response);
GET /my-index-000001/_rank_eval
{
  "requests": [
    {
      "id": "JFK query",
      "request": { "query": { "match_all": {} } },
      "ratings": []
    } ],
  "metric": {
    "recall": {
      "k": 20,
      "relevant_rating_threshold": 1
    }
  }
}

recall 指标采用以下可选参数

参数 描述

k

设置每个查询检索的最大文档数。此值将代替查询中常用的 size 参数。默认为 10。

relevant_rating_threshold

设置文档被视为“相关”的评分阈值。默认为 1

平均倒数排名
编辑

对于测试套件中的每个查询,此指标计算第一个相关文档的排名的倒数。例如,在位置 3 中找到第一个相关结果意味着倒数排名为 1/3。每个查询的倒数排名在测试套件中的所有查询中取平均值,以给出平均倒数排名

resp = client.rank_eval(
    index="my-index-000001",
    requests=[
        {
            "id": "JFK query",
            "request": {
                "query": {
                    "match_all": {}
                }
            },
            "ratings": []
        }
    ],
    metric={
        "mean_reciprocal_rank": {
            "k": 20,
            "relevant_rating_threshold": 1
        }
    },
)
print(resp)
response = client.rank_eval(
  index: 'my-index-000001',
  body: {
    requests: [
      {
        id: 'JFK query',
        request: {
          query: {
            match_all: {}
          }
        },
        ratings: []
      }
    ],
    metric: {
      mean_reciprocal_rank: {
        k: 20,
        relevant_rating_threshold: 1
      }
    }
  }
)
puts response
const response = await client.rankEval({
  index: "my-index-000001",
  requests: [
    {
      id: "JFK query",
      request: {
        query: {
          match_all: {},
        },
      },
      ratings: [],
    },
  ],
  metric: {
    mean_reciprocal_rank: {
      k: 20,
      relevant_rating_threshold: 1,
    },
  },
});
console.log(response);
GET /my-index-000001/_rank_eval
{
  "requests": [
    {
      "id": "JFK query",
      "request": { "query": { "match_all": {} } },
      "ratings": []
    } ],
  "metric": {
    "mean_reciprocal_rank": {
      "k": 20,
      "relevant_rating_threshold": 1
    }
  }
}

mean_reciprocal_rank 指标采用以下可选参数

参数 描述

k

设置每个查询检索的最大文档数。此值将代替查询中常用的 size 参数。默认为 10。

relevant_rating_threshold

设置文档被视为“相关”的评分阈值。默认为 1

折扣累积增益 (DCG)
编辑

与上述两个指标相比,折损累积增益 (discounted cumulative gain) 同时考虑了搜索结果的排名和评分。

其假设是,高度相关的文档出现在结果列表顶部时,对用户更有用。因此,DCG 公式会降低排名较低的文档的高评分对整体 DCG 指标的贡献。

resp = client.rank_eval(
    index="my-index-000001",
    requests=[
        {
            "id": "JFK query",
            "request": {
                "query": {
                    "match_all": {}
                }
            },
            "ratings": []
        }
    ],
    metric={
        "dcg": {
            "k": 20,
            "normalize": False
        }
    },
)
print(resp)
response = client.rank_eval(
  index: 'my-index-000001',
  body: {
    requests: [
      {
        id: 'JFK query',
        request: {
          query: {
            match_all: {}
          }
        },
        ratings: []
      }
    ],
    metric: {
      dcg: {
        k: 20,
        normalize: false
      }
    }
  }
)
puts response
const response = await client.rankEval({
  index: "my-index-000001",
  requests: [
    {
      id: "JFK query",
      request: {
        query: {
          match_all: {},
        },
      },
      ratings: [],
    },
  ],
  metric: {
    dcg: {
      k: 20,
      normalize: false,
    },
  },
});
console.log(response);
GET /my-index-000001/_rank_eval
{
  "requests": [
    {
      "id": "JFK query",
      "request": { "query": { "match_all": {} } },
      "ratings": []
    } ],
  "metric": {
    "dcg": {
      "k": 20,
      "normalize": false
    }
  }
}

dcg 指标接受以下可选参数:

参数 描述

k

设置每个查询检索的最大文档数。此值将代替查询中常用的 size 参数。默认为 10。

normalize

如果设置为 true,此指标将计算归一化折损累积增益 (Normalized DCG)。

预期倒数排名 (Expected Reciprocal Rank, ERR)
编辑

预期倒数排名 (ERR) 是经典倒数排名在分级相关性情况下的扩展。(Olivier Chapelle、Donald Metzler、Ya Zhang 和 Pierre Grinspan,2009 年 1 月。分级相关性的预期倒数排名。)

它基于搜索的级联模型假设,其中用户按顺序扫描排名靠前的搜索结果,并在满足信息需求的第一个文档处停止。因此,它是问题解答和导航查询的一个好指标,但对于用户有兴趣在顶部 k 个结果中找到许多相关文档的面向调查的信息需求则不那么适用。

该指标模拟了用户停止阅读结果列表的位置的倒数的期望值。这意味着,排名靠前的相关文档会对整体得分产生很大贡献。但是,如果同一文档出现在较低的排名中,它对分数的贡献会小得多;如果它前面有一些相关(但可能相关性较低)的文档,则更是如此。通过这种方式,ERR 指标会降低在非常相关的文档之后显示的文档的权重。这引入了相关文档排序中的依赖概念,而例如精确率或 DCG 并不考虑这一点。

resp = client.rank_eval(
    index="my-index-000001",
    requests=[
        {
            "id": "JFK query",
            "request": {
                "query": {
                    "match_all": {}
                }
            },
            "ratings": []
        }
    ],
    metric={
        "expected_reciprocal_rank": {
            "maximum_relevance": 3,
            "k": 20
        }
    },
)
print(resp)
response = client.rank_eval(
  index: 'my-index-000001',
  body: {
    requests: [
      {
        id: 'JFK query',
        request: {
          query: {
            match_all: {}
          }
        },
        ratings: []
      }
    ],
    metric: {
      expected_reciprocal_rank: {
        maximum_relevance: 3,
        k: 20
      }
    }
  }
)
puts response
const response = await client.rankEval({
  index: "my-index-000001",
  requests: [
    {
      id: "JFK query",
      request: {
        query: {
          match_all: {},
        },
      },
      ratings: [],
    },
  ],
  metric: {
    expected_reciprocal_rank: {
      maximum_relevance: 3,
      k: 20,
    },
  },
});
console.log(response);
GET /my-index-000001/_rank_eval
{
  "requests": [
    {
      "id": "JFK query",
      "request": { "query": { "match_all": {} } },
      "ratings": []
    } ],
  "metric": {
    "expected_reciprocal_rank": {
      "maximum_relevance": 3,
      "k": 20
    }
  }
}

expected_reciprocal_rank 指标接受以下参数:

参数 描述

maximum_relevance

必选参数。用户提供的相关性判断中使用的最高相关性等级。

k

设置每个查询检索的最大文档数。此值将代替查询中常用的 size 参数。默认为 10。

响应格式

编辑

_rank_eval 端点的响应包含为定义的质量指标计算的整体结果,一个包含测试套件中每个查询的结果细分的 details 部分,以及一个可选的 failures 部分,显示单个查询的潜在错误。响应具有以下格式:

{
  "rank_eval": {
    "metric_score": 0.4,                          
      "details": {
      "my_query_id1": {                           
        "metric_score": 0.6,                      
        "unrated_docs": [                         
          {
            "_index": "my-index-000001",
            "_id": "1960795"
          }, ...
        ],
        "hits": [
          {
            "hit": {                              
              "_index": "my-index-000001",
              "_type": "page",
              "_id": "1528558",
              "_score": 7.0556192
            },
            "rating": 1
          }, ...
        ],
        "metric_details": {                       
          "precision": {
            "relevant_docs_retrieved": 6,
            "docs_retrieved": 10
          }
        }
      },
      "my_query_id2": { [... ] }
    },
    "failures": { [... ] }
  }
}

通过定义的指标计算的整体评估质量

details 部分包含原始 requests 部分中每个查询的条目,并以搜索请求 ID 为键

details 部分中的 metric_score 显示此查询对全局质量指标分数的贡献

unrated_docs 部分包含此查询的搜索结果中每个没有评分值的文档的 _index_id 条目。这可用于要求用户提供这些文档的评分

hits 部分显示带有其提供的评分的搜索结果的分组

metric_details 提供有关计算的质量指标的附加信息(例如,检索到的文档中有多少是相关的)。内容因每个指标而异,但可以更好地解释结果