Elasticsearch + nori + 사용자사전, 유의어사전


이전 글에서 Elasticsearch 및 nori 설치를 했습니다.
elasticsearch 및 nori 설치는 이전 글을 참고 부탁드립니다.
https://sooyeol86.blogspot.com/2019/12/elasticsearch-with-nori-feat-docker.html

이번 글에서는 사용자정의 사전이나 유의어사전을 추가하는 방법에 대해서 설명을 합니다.
추가적으로 nori 필터를 사용함에 있어서 품사에 대해서 어느정도 지식이 필요할 수 있기 때문에 품사에 대한 간략한 정리도 했습니다.


Elasticsearch에 nori를 설치 하면 기본적인 형태소 분석기 및 사전을 사용할 수 있습니다.
하지만, 때때로 사용자 정의 사전이나 유의어가 필요할 수도 있겠습니다.

예를 들면 "삼성전자" 라는 단어는 사전에 없는 단어이기 때문에 아래 이미지와 같이 "삼성" / "전자" 로 단어를 분리합니다.
  


이 단어를 한 단어로 사용을 하고 싶다면 사용자 정의 사전에 추가를 해야합니다.

그리고 "삼성전자" = "삼전" 이라고 표현을 할 수도 있겠는데, 따로 유의어를 등록하지 않으면 "삼전" 이라고 했을 때 "삼성전자" 에 대해서 검색을 해오지 못합니다.
유의어 사전에 "삼성전자,삼전" 이라고 등록을 해두면 "삼전" 검색 시 "삼성전자"도 같이 검색이 되겠지요.

그럼 간략하게 진행을 해보도록 하겠습니다.


  1. 사용자 사전 파일 생성
docker-elk/elasticsearch/config/ 폴더에 user_dic.txt 파일을 생성 하고 첫번째 Line"삼성전자" 라고 등록을 합니다.


  1. 유의어 사전 파일 생성
docker-elk/elasticsearch/config/ 폴더에 synonyms.txt 파일을 생성하고 첫번째 Line"삼성전자,삼전" 이라고 등록을 합니다.

  1. docker 설정 파일에서 user_dic.txt / synoyms.txt 파일 복사하도록 설정
docker-elk/elasticsearch/Dockerfile 을 열어서 아래 내용을 추가 합니다.
COPY config/user_dic.txt config/user_dic.txt
COPY config/synonyms.txt config/synonyms.txt


  1. docker 재실행
ctrl + c 혹은 docker-compose down -v 를 통하여 docker 를 전부 종료 합니다.
docker-compose up --build -d 를 통하여 docker 를 실행합니다. (-d 옵션은 background 에서 돌리는 옵션)

  1. 파일 추가 여부 확인
docker ps 를 하고 docker-elk_elasticsearch 에 대한 container_id 를 획득하여
docer exec -it [container_id] bash 를 수행합니다. (container 내부로 접속하는 명령어)

그런다음 config 폴더를 확인해보면 아래와 같이 user_dic.txt synonyms.txt 파일이 추가 된 것을 확인할 수 있습니다.


  1. 인덱스 생성 및 테스트
아래와 같이 인덱스를 생성합니다.
아래 filter 내용을 참고하여 nori_part_of_speech 에 대한 조정이 필요한 경우 조정해야 합니다.
인터넷에 돌아다니는 예제 들의 경우 이것저것 품사들을 제거해서 실제로 원하는 analyzer를 했을 때 결과물이 안나올 가능성도 큽니다.
구축하고자 하는 사이트에 맞게 해당 필터를 사용하시기 바랍니다.


PUT test2
{
  "settings": {
    "analysis": {
      "tokenizer": {
        "nori_user_dict": {
          "type": "nori_tokenizer",
          "decompound_mode": "mixed",
          "user_dictionary": "user_dic.txt"
        }
      },
      "analyzer": {
        "korean_analyzer": {
          "filter": [
            "pos_filter_speech", "nori_readingform",
            "lowercase", "synonym", "remove_duplicates"
          ],
          "tokenizer": "nori_user_dict"
        }
      },
      "filter": {
        "synonym" : {
          "type" : "synonym_graph",
          "synonyms_path" : "synonyms.txt"
        },
        "pos_filter_speech": {
          "type": "nori_part_of_speech",
          "stoptags": [
            "E", "J", "SC", "SE", "SF", "SP", "SSC", "SSO", "SY", "VCN", "VCP",
            "VSV", "VX", "XPN", "XSA", "XSN", "XSV"
          ]
        }
      }
    }
  }
}
아래와 같이 analyze를 실행하면 "삼전" / "삼성전자" 가 나오는 것을 확인할 수 있습니다.



POST test2/_analyze
{
    "analyzer":"korean_analyzer",
    "text":"삼성전자"
}

  1. 생성한 인덱스 필터에 대한 설명
자세한 설명 및 추가 사용가능한 필터는 elasticsearch 사이트 참고

nori_part_of_speech : 품사 제거 필터

nori_readingform : 한자 to 한글 필터


synonym_graph : 유의어 필터


  1. nori_part_of_speech 필터 사용을 위한 간략한 품사 정리
nori 의 경우 lucense/mecab 기반으로 만들어졌기 때문에, mecab 사전을 참고하면 조금 도움이 될 수 있습니다.
(Tag의 경우 lucene 을 참고 하고 사전은 mecab gitgub 참고)
간략하게 예제와 품사에 대한 설명을 적긴 했지만 헷갈릴수 있으니 헷갈리면 직접 찾아보시길 권장..

E : 어미 [Verbal endings]
어간 뒤에 놓이는 굴절 접사
ex) 하고,,습니다,,

IC : 감탄사 [Interjection]
말하는 이의 본능적인 놀람이나 느낌, 부름, 응답 따위를 나타내는 말의 부류
ex) 만세,맙소사,아이고

J : 조사 [Ending Particle]
주로 체언에 붙어 뒤에 오는 다른 단어에 대하여 가지는 문법적 관계를 표시하거나 그 말의 뜻을 도와주는 품사
ex) ~보다,~까지

MAG : 부사 [General Adverb]
동사, 형용사, 동사구, 문장 전체를 수식하는 역할을 맡는 품사
ex) 힘껏,즉시,번쩍

MAJ : 접속부사 [Conjunctive adverb]
문장과 문장 사이를 접속해(연이어) 주는 부사
ex) 그러나,왜냐하면,그리고

MM : 관형사 [Determiner]
체언 앞에 놓여서 체언의 내용을 자세히 꾸며 주는 품사
ex) ,,그딴,수천수만

NNB : 의존명사 [Dependent noun(following nouns)]
의미가 형식적이어서 다른 말 아래에 기대어 쓰이는 명사
ex) ,따름,동안,무렵,이상

NNBC : 분류사 [Dependent noun]
단위를 나타내는 명사
ex) 퍼센트,군단

NNG : 보통명사 [General Noun]
일반 개념을 표시하는 명사. 여러 가지 사물의 공통된 특성을 나타낸다

NNP : 고유명사 [Proper Noun]
특정한 대상이나 유일한 대상을 가리키는 명사의 일종.

NP : 대명사 [Pronoun]
사람이나 사물, 장소를 직접 가리키는 기능을 하는 품사
ex) 이것저것,귀하,그거

NR : 수사 [Numeral]
사물의 수량이나 순서를 나타내는 단어의 한 부류
ex) ,,예닐곱,오륙백

VA : 형용사 [Adjective]
품사의 하나로 사람이나 사물의 성질과 상태 또는 존재를 나타내는 말
ex) 가녀린,잔망스럽,올바른

VCN : 부정 지정사 [Negative designator]
지정사 : 어떤 대상을 지정할 때 사용하는이다아니다를 가리키는 품사
ex) 아니,아닌

VCP : 긍정 지정사 [Positive designator]
ex) ,보이,사이

VV : 동사 [Verb]
사람이나 사물의 움직임 또는 작용을 나타내는 말

VX : 보조용언 [Auxiliary Verb or Adjective]
조적 기능을 수행하는 동사의 부류. 즉 뒤에 있는 동사구가 앞의 동사에 어떤 보조의 의미를 첨가하는 기능을 한다
ex) 헷갈리,잡수

XPN : 체언접두사 [Prefix]
체언 : 조사의 도움을 받아 문장에서 주체의 구실을 하는 단어
ex) (새 것, 새 날)

XR : 어근 [Root]
단어의 실질적 의미를 나타내는 중심 부분
ex) 불그스름,희뿌염,일목요염

XSA : 형용사 파생 접미사 [Adjective Suffix]
접미사 : 접사의 하나로 낱말의 끝에 붙어 의미를 첨가하여 다른 낱말을 이루는 말
ex) 못마땅하,스럽

XSN : 명사 파생 접미사 [Noun Suffix]
ex) 치레,투성이

XSV : 동사 파생 접미사 [Verb Suffix]
ex) 되잖,시키

NA, UNA, Unknown, VSV : 알수없는 [unknown]
SC : 구분기호 [Separator (· / :)]
SE : 생략 [Ellipsis]
SF : 물음표,느낌표,마침표 [Terminal punctuation (? ! .)]
SH : 한자 [Chinese character]
SL : 외국어 [Foreign language]
SN : 숫자 [Number]
SP : 공백 [Space]
SSC 닫는 괄호 [Closing brackets]
SSO : 여는 괄호 [Opening brackets]
SY : 기타 기호 [Other symbol]


추가적으로 아래 사이트를 참고 하면 도움이 될듯 합니다.

댓글 8개:

  1. 글 내용이 아주 큰 도움이 되었습니다 잘 보고 가요

    답글삭제
    답글
    1. 도움이 되셨다니 기분이 좋네요! 감사합니다.

      삭제
  2. 굳굳.. 좋은글 감사합니다.

    답글삭제
  3. 실제 운영하고 있는 인스턴스에서 user_dic과 synonyms가 업데이트가 필요한 경우엔 어떻게 하시는지 궁금합니다 :)

    답글삭제
  4. 안녕하세요..
    저는 따로 배우고 했거나.. 심도 깊게 연구를 하고 사용한 것은 아니고, 소규모 검색엔진이 필요한 곳에서 사용을 했었습니다.
    저 같은 경우는 es 올려둔 서버에 파일을 업데이트 하고 es 재기동을 통하여 업데이트를 진행했습니다.
    그렇게 했던 이유는 색인을 할 때는 user_dic 도 사용을 하여 색인을 했지만.. synonyms 의 경우는 별도 색인 없이 검색 시 검색 쿼리를 사용할 때 사용을 했던 것으로 기억합니다.
    user_dic 의 경우 이미 색인이 된 데이터의 경우 재색인을 해주지 않을 경우 매칭이 안될 것 같기는 하나, 그 정도까지 타이트하게 관리할 필요는 없었어서 해당 방법으로 했습니다.

    전문적으로 심도 깊게 사용하시는 분들은 어떻게 하시는지 저도 궁금하네요..
    다른 분들의 경우도 어떻게 하는지 알게 되시면 댓글로 링크라도 부탁드립니다!

    좋은 하루 되세요 :)

    답글삭제
  5. 감사합니다. 덕분에 실습하는 환경 잘 구축했습니다.!

    답글삭제
    답글
    1. 안녕하세요. 오래전 글인데도 도움이 되었다니 기분이 좋네요! 좋은 하루 되세요 :)

      삭제

간단한 AWS 웹 서버 구축 with mongodb (feat. Github and Docker)

오랫만에 블로그에 게시글을 업데이트 해봅니다. 최근에 AWS 로 서버 구축하는 것을 테스트 해본 것이 있어서, 이번 게시글에서는 AWS 를 사용하여 간단하게 웹 서버 구축하는 것을 진행하려고 합니다. AWS EC2 서버 프리티어 버전으로 1대 발급 받...