Blog

2018.08.15 - 번역 - Test-Driven Relevance Tuning of Elasticsearch using the Ranking Evaluation API ...

drscg 2019. 1. 7. 14:32

This blog post is written for engineers that are always looking for ways to improve the result sets of their search application built on Elasticsearch. The goal of this post is to raise awareness of why you should care about relevance, what components are involved and how you can control them.

이 게시물은 Elasticsearch에 구축된 search application의 결과 집합을 개선하는 방법을 모색하고 있는 엔지니어를 위해 작성되었다. 이 게시물의 목표는 relevance에 주의해야 하는 이유, 그것에 포함된 구성요소, 그것을 제어하는 방법에 대한 관심을 높이는데 있다.

Tuning relevance can be hard. But by the end of this blogpost you’ll have a better understanding of how you can tune the relevance of your search engine and learn that it's actually not so hard with the right tools.

relevance를 tuning하는 것은 어려울 수 있다. 그러나 이 게시물의 마지막 부분에 이르면, search engine의 relevance를 tuning하는 방법을 더 잘 이해할 것이고, 올바른 tool을 사용하면 실제로 그렇게 어렵지 않다는 것을 배우게 될 것이다.

Let's start with a bit of theory

Let's consider a search application to use a combination of data (index), data models (mapping and analyzers) and query templates (Query DSL). Using the search system means entering queries (typically a set of parameters, such as query string, filters, etc.) and receiving results. The consumer of the results can be a person that accesses the search engine via a web-based GUI or an automated system (I will mainly talk about users during this blogpost, but it’s also applicable for bots). Those results may or may not match the users expectations.

data(index), model(mapping과 analyzer), query template(query DSL)의 조합을 사용하는 search application을 생각해 보자. search system을 사용한다는 것은 query(일반적으로 query string, filter 등의 매개변수 집합)를 입력하고, 결과를 받는다는 것이다. 결과를 사용하는 사람은 web 기반 GUI나 자동화된 system을 통해 search engine에 access하는 사람이 될 수 있다. (이 게시물에서는 주로 사용자에 대해 이야기하겠지만, bots에 대해서도 적용될 수 있다.) 이들 결과는 사용자의 기대와 다를 수도 있다.

The job of a developer that builds a search application is to make sure that their users will find what they are looking for. Optimizing the search engine for this is what we call relevance tuning.

search application을 구축하는 개발자의 job은 사용자가 찾고자 하는 것을 사용자가 찾을 수 있도록 하는 것이다. 이를 위해 search engine을 최적화하는 것을 relevance tuning이라 한다.

Ultimately, relevance is typically very subjective and often depends the individual evaluating the results of the query. Whether a user will be happy with the results or not — which is ultimately the only relevant metric for relevance — is hard to predict.

궁극적으로, relevance는 대개 매우 주관적이며, 종종 query 결과에 대한 개인적인 평가에 따라 다르다. 사용자가 결과에 만족할지 여부(이는 궁극적으로 relevance에 대한 relevant metric일 뿐이다)는 예측하기 어렵다.

Every dataset is unique, as are your users. This means that ultimately nobody can tell you exactly which configuration to choose. Even if there was a database full of use cases that included feedback about what worked well, your case will always be specific and unique.

모든 data 집합은 사용자와 마찬가지로 고유하다. 이것은 궁극적으로 어떤 구성을 선택해야 할지 아무도 정확히 알 수 없다는 것을 의미한다. 잘 동작하는 지에 대한 feedback을 포함하고 있는 사용 사례로 가득찬 database가 있더라고, 여러분의 사례는 항상 독특하고 고유할 것이다.

Very often, customers ask which query they should use. Of course, we can give guidelines that serve as a starting point. For example, it is best practice to use a multi-match query in an eCommerce use case. This usually works well until some edge cases are discovered that should yield better results. And when it comes to this kind of tuning it is usually better to follow a test-driven approach as explained in the following:

매우 자주, 고객등은 그들이 어떤 query를 사용해야 할지를 질문한다. 물론, 출발점 역활을 하는 가이드라인을 제공할 수 있다. 예를 들어, eCommerce 사례에서는 multi-match query를 사용하는 것이 가장 좋다. 보통 이것은 더 나은 결과를 산출해야 하는 어떤 상황이 발생할 때까지는 잘 동작한다. 그리고 이런 종류의 tuning에 대해서는, 다음과 같은 test-driven 방식을 따르는 것이 더 낫다.

  • Let's consider relevance tuning to be an optimization problem.
    relevance tuning을 최적화 문제로 고려하자.
  • There are lots of moving parts for a data model and a query template.
    data model과 query template에는 많은 유동적인 부분이 있다.
  • Finding the perfect combination of all those variables is the ultimate goal.
    모든 변수의 완변한 조합을 찾는 것이 최종 목표이다.

There are dozens of ways to setup a query template and hundreds of ways to configure your data model including all options for setting up analyzers. Sometimes relevance isn't your only concern. Query speed and required disk space are usually also important factors. But let's consider them as small constraints in our quest to optimize relevance.

query template을 설정하는 수십가지 방법과 analyzer 설정에 대한 모든 option을 포함하여 data model을 구성하는 수백가지 방법이 있다. 때로는 relevance가 유일한 관심사가 아니다. query 속도와 disk 공간도 일반적으로 중요한 요소이다. 그러나, relevance를 최적화하기 위한 우리의 목표에서 이들을 작은 제약으로 생각하자.

To be successful you need a tool that enables you to measure and tune the relevance for your users and your search engine. Such a tool became available with version 6.2 of Elasticsearch, namely the Ranking Evaluation API.

이를 위해, 사용자와 search engine의 relevance를 측정하고 tuning을 할 수 있는 tool이 필요하다. 그런 tool을 Elasticsearch 6.2에서 Ranking Evaluation API라는 이름으로 이용할 수 있게 되었다.

Using the Ranking Evaluation API

With the Ranking Evaluation API, it is possible to measure the search quality of your search engine. To use this API, you’ll need an existing index, a set of queries, and a list of relevance judgements for documents returned by those queries. Relevance judgements are labels that indicate whether a document matched a query well or not.

Ranking Evaluation API를 사용하면, search engine의 search 품질을 측정할 수 있다. 이 API를 사용하기 위해서는 기존의 index, query 집합, 해당 query에 의해 반환되는 document에 대해 relevance를 판단할 목록이 필요하다. relevance 판단은 document가 query와 잘 일치하는지 여부를 나타내는 label이다.

Usually you know the queries that you use. Either they can be extracted from the application code or from the slowlogs (Turning the slowlog setting to 0 seconds will log all queries. Warning: Don’t let this setting run in production for a long time, as it will impact performance.). If you use search templates, it’s very straightforward to extract the queries in JSON format.

일반적으로, 여러분은 여러분이 사용하는 query를 알고 있다. application code 또는 slowlogs (slowlog를 0초로 설정하는 것은 모든 query를 log로 남기겠다는 의미이다. 경고: 이 설정은 성능에 영향을 미치므로, 제품에서 오랫동안 실행하지 않도록 하자)에서 추출할 수 있다. search templates을 사용한다면, query를 JSON format으로 추출하는 것은 매우 간단하다.

The only tedious part is to gather the relevance judgements. You’ll need to collect for each query one or more documents that should match that query or not. In many cases this will be manual work. The exact format of the relevance judgements is explained in the ranking evaluation documentation.

유일하게 지루한 부분은 relevance 판단을 수집하는 것이다. 각 query에 대해 일치하거나 일치하지 않는 하나 이상의 document를 수집해야 한다. 많은 경우에, 이것은 수작업이다. relevance 판단의 정확한 형식은 ranking evaluation documentation에 설명되어 있다.

Search quality can also be measured using proven information retrieval metrics like precision, mean reciprocal rank or discounted cumulative gain (DCG).

search 품질은 precision, mean reciprocal rank, discounted cumulative gain (DCG) 같은 증명된 정보 검색 통계를 사용하여 측정할 수도 있다.

The queries you pick should be a somewhat representative sample of typical queries that you will serve in production. The easiest way to pick the sample if you already have a search system in place would be to take the top 100 queries from your website analytics logs.

여러분이 선택해야 하는 query는 제품에서 서비스할 전형적인 query의 대표적인 예제라야 한다. search system을 이미 가지고 있다면, 예제를 선택하는 가장 쉬운 방법은 여러분의 website 분석 로그에서 상위 100개의 query를 가져오는 것이다.

Let’s assume you’re ready to go now: You have an index, query samples and relevance judgements. Here’s a little recipe how you can use the Ranking Evaluation API for test driven relevance tuning:

이제 준비가 되었다고 가정라자. index, query 예제, relevance 판단을 가지고 있다. 다음은 test driven relevance tuning을 위해 Ranking Evaluation API를 사용하는 방법에 대한 약간의 recipe이다.

  1. Talk to QA, and find out which problematic queries need to be tuned.
    QA와 이야기하여, tuning해야 할 문제가 있는 query가 어떤 것인지 알아보자.
  2. Run the queries that need to be tuned. For this example, we have 1 document in our movies index:
    tuning해야 할 query를 실행하자. 이 예제를 위하여, movies index에는 1개의 document가 있다.
    POST movies/doc
    {
      "title": "Star Wars"
    }
        
    Let’s check if a query for “Star Trek” yields results:
    “Star Trek”에 대한 query 결과가 나오는지 확인하자.
    GET movies/_rank_eval
    {
      "requests": [
        {
          "id": "star_trek",
          "request": {
            "query": {
              "match_phrase": {
                "title": "Star Trek"
              }
            }
          },
          "ratings": [
            {
              "_index": "movies",
              "_id": "1",
              "rating": 1
            }
          ]
        }
      ],
      "metric": {
        "precision": {
          "k": 5,
          "relevant_rating_threshold": 1
        }
      }
    }
        
  3. Run an initial test to measure the current state of your system:
    시스템의 현재 상태를 측정하기 위해 초기 테스트를 실행하자.

    {
      "quality_level": 0,
      "details": {
        "star_trek": {
          "quality_level": 0,
          "unknown_docs": [],
          "hits": [],
          "metric_details": {
            "precision": {
              "relevant_docs_retrieved": 0,
              "docs_retrieved": 0
            }
          }
        }
      },
      "failures": {}
    }
        
    Ok the quality_level is 0. This is not what we want. The quality level can range from 0 to 1. We should aim for something close to 1. So maybe we have to use a different query.
    좋다. quality_level이 0 이다. 이것은 우리가 원하던 것이 아니다. quality level의 범위는 0에서 1까지이다. 1 에 가까운 값을 목표로 해야 한다. 따라서, 아마도 다른 query를 사용해야 한다.

  4. Change a variable. For this example, let's change the query type.
    변수를 바꾸자. 예를 들자면, query type을 변경하자.

    GET movies/_rank_eval
    {
      "requests": [
        {
          "id": "star_trek",
          "request": {
            "query": {
              "match": {
                "title": "Star Trek"
              }
            }
          },
          "ratings": [
            {
              "_index": "movies",
              "_id": "1",
              "rating": 1
            }
          ]
        }
      ],
      "metric": {
        "precision": {
          "k": 5,
          "relevant_rating_threshold": 1
        }
      }
    }
        
  5. Run the test again.
    테스트를 다시 실행하자.

    {
      "quality_level": 1,
      "details": {
        "star_trek": {
          "quality_level": 1,
          "unknown_docs": [],
          "hits": [
            {
              "hit": {
                "_index": "movies",
                "_type": "doc",
                "_id": "1",
                "_score": 0.2876821
              },
              "rating": 1
            }
          ],
          "metric_details": {
            "precision": {
              "relevant_docs_retrieved": 1,
              "docs_retrieved": 1
            }
          }
        }
      },
      "failures": {}
    }
        

    A lot better. Now we could find something. This is just an example to illustrate the workflow. (Note: A more detailed walkthrough of this process will be contained in a follow up blogpost to this topic.)
    훨씬 나아졌다. 이제 무언가를 찾을 수 있다. 이것은 작업 흐름을 설명하는 예시일 뿐이다. (Note: 이 process의 더 자세한 내용은 이 게시물의 후속 게시물에 포함되어 있다.)

  6. At this point, you have two options:
    이 시점에서, 여러분은 2가지 옵션을 가진다.

    • If the overall quality increases and meets your quality SLAs, you’re done, otherwise repeat until you reach the desired quality.
      전반적인 품질이 증가하고, 품질 SLA를 만족하면, 완료되었다. 그렇지 않으면, 원하는 품질에 이를 때까지 반복한다.
    • If the overall quality decreases, revert the change, make a note of it for future reference and try something else.
      전반적인 품질이 떨어지면, 변경을 되돌리고, 나중에 참조할 수 있도록 메모해 두고, 다른 것을 시도하자.

Just remember: Ranking evaluation should be repeated periodically as data, users, and/or queries change. Every changing variable can affect relevancy (different index size, different data, different query templates, etc.). Please keep in mind, that it is usually not possible to completely exhaust every possible search. The number of questions (queries) and possible answers (results) is just too open and large to be evaluated scientifically with full test coverage.

data, 사용자, query가 변경되면, ranking evaluation을 주기적으로 반복해야 한다는 점을 기억하자. 변화하는 모든 변수(index size, data, query template 등)는 relevance에 영향을 미칠 수 있다. 일반적으로 가능한 모든 search를 완벽하게 하는 것은 불가능하다는 점을 기억하자. 질문(query)의 수와 가능한 답변(query)의 수는 너무 광범위하여, 전체 테스트 범위를 과학적으로 평가할 수는 없다.

In some cases, when you use your search engine to perform matching (e.g. name matching) and look for one specific result (or very few), then you could theoretically test it completely and your evaluation result would be a lot more representative. In most cases though you can only do partial testing of a sample. This is the reason why you should try to pick a representative sample of queries and you should try to work with realistic relevance judgements.

경우에 따라, search engine을 사용하여 match(예: 이름 match)를 수행하고, 하나의 특정 결과(또는 매우 작은)를 찾는 경우, 이론적으로 그것을 완벽하게 테스트할 수 있고, 평가 결과가 훨씬 더 대표적인 사례가 될 수 있다. 대부분의 경우 예제에 대한 부분적인 테스트만 할 수 있다. 이것이 query에 대한 대표적인 예제를 선택해야 하고 현실적인 relevance 판단을 가지고 작업해야 하는 이유이다.

Good luck with tuning relevance. As you start to use the Ranking Evaluation API, let us know about your feedback and experiences on our Discuss forum.

relevance tuning에 행운을 빈다. Ranking Evaluation API의 사용을 시작하면서, 여러분의 의견 및 경험에 대해 discuss forum에 알려주기 바란다.

원문 : Test-Driven Relevance Tuning of Elasticsearch using the Ranking Evaluation API