개요
영문으로 작성된 문서의 경우 go, went처럼 철자는 다른 단어지만, 특수한 과거형 같이 같은 의미를 가지는 단어에 대해 검색 결과는 같은 검색 결과를 보여줘야 한다. 이를 위해 다양한 기법이 있지만 stemming을(어간 추출) 통해 처리하는 방법에 대하여 알아본다.
Stemming(어간 추출)
어간을(stem) 추출하는 작업ㅇ을 어간 추출(stemming)이라고 한다. 어간 추출은 형태학적 분석을 단순화한 버전이라고 볼 수도 있고, 정해진 규칙만 보고 단어의 어미를 자르는 어림짐작의 작업이라고 볼 수 있다. 이 작업은 섬세한 작업이 아니기 때문에 어간 추출 후에 나오는 단어는 사전에 존재하지 않은 단어이거나 의미가 다른 단어 일 수 있다. 아래 예제들을 살펴보면서 자세히 알아보자.
Stemmer 사용
Elasticserach의 stemmer를 사용하면 입력된 단어들에 대하여 어간 추출된 결과를 확인할 수 있다. 일반적인 단어에 대해서는 문제없이 어간 추출이 되지만 규칙에 기반한 알고리즘은 종종 제대로 된 일반화를 수행하지 못할 수 있다. (지나치게 되거나, 또는 덜 되거나)
stemmer 적용
입력 단어 | stemmer 적용 |
formalize | formal |
allowance | allow |
electricial | electric |
passed | pass |
organization | organ |
forgot | forgot |
organization을 어간 추출 했을때 organ이라는 결과를 얻을 수 있다. organization과 organ은 다른 단어임에도 어간 추출 결과로는 같은 단어로 추출되어 동일한 어간을 가지게 된다.
forgot의 경우 forget의 과겨형으로 forget으로 어간 추출이 되기를 희망하지만 passed가 pass로 어간 추출된 것과는 다르게 forgot 그대로 추출됨을 볼 수 있다.
# Request
GET /_analyze
{
"tokenizer": "standard",
"filter": ["stemmer"],
"text": ["formalize", "allowance", "electricial", "passed", "organization", "forgot"]
}
# Response
{
"tokens": [
{
"token": "formal",
.....
},
{
"token": "allow",
.....
},
{
"token": "electric",
.....
},
{
"token": "pass",
.....
},
{
"token": "organ",
.....
},
{
"token": "forgot"
.....
}
]
}
Elasticsearch Stemming
Elasticsearch에서 어간 추출은 stemmer token filter에러 처리된다. 이러한 토큰 필터는 단어를 어떻게 어간 추출하는지에 따라 2가지 방법으로 분류할 수 있다.
- Algorithmic stemmers: 일련의 규칙을 기반으로 단어를 어간화 한다.
- Dictionary stemmers: 사전에 단어를 검색하여 단어를 어간화 한다.
어간 추출은 토큰을 변경하기 때문에 인덱스 및 검색 분석 중 동일한 어간 추출 토큰 필요를 사용해야 한다.
Algorithmic stemmers
알고리즘적 스테머는 각 단어에 일련의 규칙을 적용하여 어근 혈태로 축소 한다. 예를 들어 영어의 복수형 단어의 끝에서 -s, -es로 끝나는 경우 접미사를 제거하여 어간을 분리할 수 있다.
장점
- 별도의 플러그인 설치가 필요 없고, 일반적으로 바로 사용해도 잘 동작한다.
- 메모리를 거의 사용하지 않는다.
- 일반적으로 사전 스테머 방식보다 빠르게 동작한다.
단점
- 어근 형태가 없는 불규칙 단어는 잘 동작하지 않는다.
- ex) be, are, am
- mouse, mice
Elasticsearch에서 제공하는 토큰 필터
- Stemmer: 다양한 언어에 대하여 사용이 가능하다 https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis-stemmer-tokenfilter.html
- KStem: 알고리즘적 어간 추출과 내장 사전을 결합한 영어 어간 추출기 https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis-kstem-tokenfilter.html
- Porter stem: 영어에 대한 Elasticsearch에서 추천하는 알고리즘 형태소 분석기 https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis-porterstem-tokenfilter.html
- Snowball: 여러 언어에 대하여 Snowball 기반 어간 추출 규칙을 사용하는 분석기 https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis-snowball-tokenfilter.html
Dictaionary stemmers
사전 어간 분석기는 제공된 사전에서 단어를 찾고, 어간이 제거되지 않는 단어 변형을 사전에서 어간이 제거된 단어로 대체한다.
장점
- 불규칙 단어의 어간 분석 가능
- 철자는 비슷하지만 개념적으로 관련이 없는 단어를 구별가능
단점
- 사전 품질: 사전 스테머는 사전만큼만 잘 동작한다. 정기적인 사전 업데이트가 필요하다.
- 크기 및 성능: 모든 단어, 접두어, 접미사를 사전에서 메모리로 로드해야 한다. 이는 RAM을 상당량 소모한다.
Elasticsearch에서 제공하는 토큰 필터
- Hunspell: 사전 어간 분석 기능을 제공한다. https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis-hunspell-tokenfilter.html
가능하다면 사전 토큰 필터를 사용하기 전에 해당 언어에 대한 알고리즘 스테머를 먼저 사용해 보는 것이 좋다.
Control stemming
어간 추출은 철자가 비슷하지만 개념적으로 관련이 없는 어근을 생성할 수 있다. 예를 들어 skies, skiing은 다른 단어지만 ski라는 단어로 어근 추출된다.
이를 방지하고 어간 추출을 더 효과적으로 제어하려면 다음 토큰 필터를 사용할 수 있다.
- stemmer override: 특정 토큰의 어간 추출에 대한 규칙을 정의한다. https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis-stemmer-override-tokenfilter.html
- keyword marker: 지정된 토큰을 키워드로 표시한다. https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis-keyword-marker-tokenfilter.html
- conditinal: keyword marker 필터와 유사하게 토큰을 키워드로 표시하는 데 사용 가능하다. https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis-condition-tokenfilter.html
Stemming 테스트
stemmer, porter_stem, hunspell 각 3가지 토큰 필터를 사용하여 각 단어들에 대하여 어근 추출 결과를 비교해 본다.
테스트 방법
# stemmer
GET /_analyze
{
"tokenizer": "standard",
"filter": ["stemmer"],
"text": ["entered"]
}
# porter_stem
GET /_analyze
{
"tokenizer": "standard",
"filter": ["porter_stem"],
"text": ["entered"]
}
# hunspell
GET /_analyze
{
"tokenizer": "standard",
"filter": [
{
"type": "hunspell",
"locale": "en_US",
"dedup": true
}
],
"text": ["entered"]
}
테스트 결과
stemmer | porter_stem | hunspell | |
forgot | forgot | forgot | forgot |
organization | organ | organ | organization |
broker | broker | broker | broker broke |
entered | enter | enter | entered enter |
the character died | the character di | the character di | the character die |
he was kind | he wa kind | he wa kind | he was kind |
테스트 결과를 보면 일반적인 케이스에 대해서는 모든 토큰 필터가 정상적으로 어간 추출을 해준다.
broker처럼 특수한 단어에 대해서는 hunspell 토큰 필터만 broker broke로 어간 분리 결과를 보여준다.
하지만 fotgot에 대해서는 모든 토큰 필더가 forget으로 어간 추출이 가능하지는 않다.
공식적인 Elasticsearch의 가이드는 아니지만 forget처럼 어간 추출이 불가능한 단어에 대해서는 동의어 필터를 통하여 처리하는 방법이 소개되고 있다.
아래 동의어 처리 예제를 참고한다.
# Request
GET /_analyze
{
"tokenizer": "standard",
"filter": [
{
"type": "synonym_graph",
"synonyms": ["forgot, forget"]
}
],
"text": ["forgot"]
}
# Response
{
"tokens": [
{
"token": "forget",
......
},
{
"token": "forgot",
......
}
]
}
참고
https://www.elastic.co/guide/en/elasticsearch/reference/current/stemming.html
'dev > elasticsearch' 카테고리의 다른 글
Elasticsearch hybrid search with RRF(Reciprocal rank fusion) (0) | 2024.12.03 |
---|---|
Elasticsearch 시맨틱 검색(semantic search) (1) | 2024.11.27 |
Elasticsearch - fuzzy query (0) | 2024.06.03 |
Elasticsearch - Dense vector field type (1) | 2024.06.03 |
elasticsearch 2.0 Getting Started (0) | 2015.11.04 |