Database/NOSQL

Elastic Search - 검색 정확도(3)

류큐큐 2024. 4. 4. 17:58

이전 포스팅에서 우린 정확도에 대한 문제를 직면했다.

이 정확도에 대해 자세히 알아보고 어떻게 쿼리를 작성해야할지 알아보자.

엘라스틱 서치의 검색 결과 리스폰스를 보면 

_score 필드를 볼 수 있다.

"max_score": 4.603986,
        "hits": [
            {
                "_index": "set_of_search_index",
                "_id": "3",
                "_score": 4.603986,
                "_source": {
                    "message": "메종키츠네 폭스헤드 우먼즈 반팔티 블랙 AW00103KJ0005-P199"
                }
            },
            {
                "_index": "set_of_search_index",
                "_id": "4",
                "_score": 2.9436355,
                "_source": {
                    "message": "메종키츠네 폭스헤드 우먼즈 반팔티 화이트 AW00103KJ0005-P100"
                }
            }
        ]



이는 직관적으로 검색 결과에 대한 점수를 수치화 한것이고 max_score는 검색 결과중 가장 높은 정확도 점수를 나타낸것이다.

그럼 이 정확도에 대한 점수를 계산하는 기준은 무엇이냐

바로 BM25라는 알고리즘이다.

찾아보면 계산식이 복잡해 보이는데 우린 저걸 사용하는 사람 입장이니 저 알고리즘의 크게 작용하는 3가지에 대해만 알고 해당 컨셉을 이해하자.

TF (Term Frequency)

말 그대로 용어 빈도다.

메종키츠네 반팔 이라는 검색을 한다 했을때 메종키츠네 반팔이 1번 써져있는 곳보다  100번 써져있는 곳이 내가 좀 더 보고싶은 결과물일 확률 이높다.

내가 검색하고자 타겟이 검색 타겟 필드에 (상품명 , 본문 등등..) 에 많이 나타날수록 저 TF 점수가 높아진다 . 그리고 이 TF 점수는 25점이 최대이다.

IDF (Inverse Document Frequency)

한글로 직역해보자면 역 문서 빈도 인데 

이건 메종키츠네 반팔 로 검색을 했을 때 '메종키츠네' 와 '반팔' 이 두 단어를 포함하고 있는 여러 상품들이 있다치면

메종키츠네가 100개  반팔이 10개 라고 하면 메종키츠네보다 적게나온 반팔이 더 중요한 단어일 수 있다라는 개념으로 빈도수가 많이 나오는 용어의 점수가 감소하는것을 IDF라 한다. 

Field Length 

마지막으로 필드 길이인데 이건 문서에서 더 짧은곳에 해당 단어가 있다면 긴 필드를 가진 곳 보다 그 짧은 필드를  가진 곳에서 점수가 더 높게 나온다.

이 세가지 개념에 대해 숙지하고

엘라스틱 서치가 어떻게 정확도를 분석하는지 대략적으로 알아보자.


"메종키츠네 폭스헤드 우먼즈 반팔티 블랙 AW00103KJ0005-P199"

"메종 키츠네 폭스 헤드 여성 반팔 티 블랙 AW00103KJ0005-P199"
"메종키츠네 폭스헤드 우먼즈 반팔티 화이트 AW00103KJ0005-P100"


이 세가지 상품명을 엘라스틱서치에 인덱싱한다고 치면

엘라스틱 서치엔 역 인덱스(inverted index)라는 구조로 위의 글들을 저장한다.

 

이 역 인덱스는 아래 그림 처럼 해당 단어가 어느 페이지에 있는지 나타내는것에 비유할 수 있다.
이렇게 추출된 단어를 term이라 한다.



이 역 인덱스 구조를 갖고 있기 때문에 데이터가 많아져도 Rdbs처럼 특정 필드의 값을 전부 풀 스캐닝해야하는것이 아니라
각각의 term의 위치를 나타내는 값이 추가되는것뿐이라 빠른속도로 검색을 할 수 있다.

그래서 엘라스틱 서치는 내가 특정 단어에대해 색인을 하면 그걸 분석하고 저렇게 term들로 분리시켜 놓는데

Text Analysis를 하는 것이 바로 analyzer이다 

analyzer는 0~3개의 Character Filter와 1개의 Tokenizer 그리고 다수의 Token Filter 로 이루어져 있다.


이걸 굳이 알아야하나 싶긴한데 나중에 색인화 과정을 할때 직접 세팅해야하는 부분들이 있어서 알고있어야만 정확하게 색인화를 할 수 있다.

그럼 순서대로 최대한 간단하게 설명해보자면 

Character Filter
텍스트를 특정 문자로 대치하거나 제거하는 것을 담당한다.
3가지에 대해 간단하게 알아보면
 - HTML Strip 
   html 태그 형식의 값을 넣으면 html 태그들을 다 벗겨낸다.

 - Mapping
  보편적으로 가장 많이 쓰인다.  최대한 간단하게 설명하자면 많은 analyzer는 특수문자를 불용어로 간주하여 제거해버려 term에서 저장되질 않아 특수문자를 특정 단어로 치환해서 색인할때 사용한다.

 - Pattern Replace
   정규식을 사용하여 복잡한 패턴들을 치환할수 있게 해준다.  

 


Tokenizer

단어들을 하나의 term 단위로 분리하는 과정을 담당한다. 이 Tokenizer는 반드시 1개만 적용이 가능하다.

Token Filter
그리고 이렇게 분리된 term들을 가공하는 역할을 한다. Tokenizer에 의해 분리된 단어 예를들면 영어 The Brown이 
'The',  'Brown' 이렇게 2개의 term으로 분리된다고 쳤을때 이 두단어를 소문자로 바꾸고 싶다면 해당 기능을 하는 Token Filter를 적용하면 term들이 'the', 'brown'으로 변형되어 색인된다.


 

이제 엘라스틱 서치에서 정확도와 관련 있는 쿼리에 대해 알아보자.