사용자 스토리

Elasticsearch로 간편해진 텍스트 분류

Elasticsearch는 검색 및 분석 엔진으로 널리 사용되고 있지만, 텍스트 마이닝 API로서의 기능은 잘 알려져 있지 않습니다.

저는 다음 글을 통해 Elasticsearch로 텍스트 분류를 수행하는 방법을 보여드리려고 합니다. 컴퓨터 언어학에 대한 전공 지식과 텍스트 마이닝 분야 프리랜서로서 수년간의 비즈니스 경험을 바탕으로, 다양한 시나리오에서 다음과 같은 기법을 구현하고 테스트할 기회가 있었습니다.

Elasticsearch를 처음 접했을 때 사용 편의성, 속도 및 구성 옵션에 매료되었습니다. Elasticsearch로 작업할 때마다, 기존의 자연어 처리(NLP) 도구와 기법으로 처리했던 것을 훨씬 더 간단하게 해결할 수 있는 방법을 발견하게 되었습니다.

어느 순간 저는 맨 처음부터 시작하여 구현하도록 교육받은 많은 것을 Elasticsearch를 사용해 즉시 해결할 수 있다는 것을 깨달았습니다.

대부분의 NLP 작업은 표준 전처리 파이프라인으로 시작합니다.

  1. 데이터 수집
  2. 원시 텍스트 추출
  3. 문장 분리
  4. 토큰화
  5. 정규화(어간 추출, 원형 복원)
  6. 불용어 제거
  7. 품사 태깅

구문 분석과 같은 일부 NLP 작업에는 심층적인 언어 분석이 필요합니다.

이러한 종류의 작업에 대해서도 Elasticsearch에서 즉시 이상적인 아키텍처와 데이터 형식을 제공하는 것은 아닙니다. 즉, 토큰 수준을 넘어서는 작업의 경우 전체 텍스트에 액세스하는 사용자 정의 플러그인을 작성하거나 사용해야 합니다.

그러나 분류, 군집화, 키워드 추출, 유사도 측정 등과 같은 작업에는 주어진 문서의 표준화되고 가중치가 적용된 Bag of Words(BoW) 표현만 있으면 됩니다.

1단계와 2단계는 Elasticsearch의 Ingest Attachment Processor Plugin(5.0 이전 명칭은 Mapper Attachments Plugin)을 통해 해결할 수 있습니다.

이러한 플러그인의 원시 텍스트 추출 기능은 Apache Tika를 기반으로 하며 가장 일반적인 데이터 형식(HTML/PDF/Word 등)에서 작동합니다.

4단계에서 6단계는 언어 분석기를 사용하면 즉시 해결됩니다.

샘플 매핑:

  {
    "properties":{
       "content":{
          "type":"text",
          "analyzer":"german"
       }
    }
  }

특정 필드의 매핑 유형이 "text"(5.0 이전: "analyzed string")이고 분석기가 Elasticsearch에서 기본적으로 지원하는 언어 중 하나로 설정된 경우, 토큰화, 어간 추출 및 불용어 제거는 인덱스 시간에 자동으로 수행됩니다.

따라서 Apache Tika에서 지원하는 모든 종류의 문서에서 Bag of Words(BoW) 표현을 가져오는 데는 사용자 정의 코드나 다른 도구가 필요하지 않습니다.

언어 분석기는 Elasticsearch가 실행될 때 REST API를 통해 호출할 수도 있습니다.

curl -XGET "http://localhost:9200/_analyze?analyzer=english" -d'
  {
   "text" : "This is a test."
  }'
  {
    "tokens":[
       {
          "token":"test",
          "start_offset":10,
          "end_offset":14,
          "type":"<ALPHANUM>",
          "position":3
       }
    ]
  }

비-Elasticsearch 접근 방식은 다음과 같습니다.

사용자 정의 코드를 사용하여 텍스트를 수집하고, 수동으로 또는 Tika 라이브러리를 사용하여 문서를 구문 분석하고, NLTK, OpenNLP, Stanford NLP, Spacy, 또는 연구 부서에서 개발한 다른 도구 등과 같은 전통적인 NLP 라이브러리나 API를 사용합니다. 그러나 연구 부서에서 개발한 도구는 대개 엔터프라이즈 컨텍스트에 그다지 유용하지 않습니다. 데이터 형식이 독점적인 경우가 매우 많고, 도구를 명령줄에서 컴파일하고 실행해야 하며, 그 결과는 표준 출력으로 간단하게 제공되는 경우가 대부분입니다. REST API는 예외입니다.

반면에 Elasticsearch 언어 분석기를 사용하면 매핑을 구성하고 데이터를 색인하기만 하면 됩니다. 전처리는 인덱스 시간에 자동으로 수행됩니다.

텍스트 분류에 대한 전통적인 접근 방식

전통적으로 텍스트 분류는 비자율 머신 러닝으로 처리하는 작업입니다. 모델 훈련을 위한 입력은 레이블이 지정된 문서 세트입니다. 이러한 입력의 최소 표현은 다음 두 개의 필드가 있는 JSON 문서입니다.

"content" 및 "category"

전통적으로 텍스트 분류는 SciKit Learn, Weka, NLTK, Apache Mahout등과 같은 도구를 사용하여 처리할 수 있습니다.

모델 생성

대부분의 머신 러닝 알고리즘에는 데이터의 벡터 공간 모델 표현이 필요합니다. 특징 공간은 일반적으로 주어진 데이터 세트에서 가장 중요한 10,000개의 단어가 될 수 있습니다. 단어의 중요도는 어떻게 측정할 수 있을까요?

일반적으로 TF-IDF를 사용하는데, 이는 20세기인 1970년대에 발명된 공식입니다. TF-IDF는 나머지 데이터 세트와 비교하여 주어진 문서 내 용어의 점수를 매기는 가중치입니다. 문서에 있는 용어의 TF-IDF 점수가 높으면 이는 매우 특징적인 키워드이며 해당 단어를 사용하여 한 문서를 다른 모든 문서와 구별한다는 것을 의미합니다.

문서 하위 집합에서 TF-IDF 점수가 가장 높은 키워드는 주제를 나타낼 수 있습니다. 텍스트 분류의 경우 특징 공간에 전반적인 TF-IDF 점수가 가장 높은 n개의 단어가 포함되는 것이 일반적입니다.

각 문서는 특징 벡터로 변환된 다음 각 클래스/카테고리에 대한 모든 훈련 인스턴스를 사용하여 모델이 생성됩니다. 그런 다음 이 모델에 따라 새 문서를 분류할 수 있습니다. 따라서 문서를 특징 벡터로 변환해야 하며 여기에서 모든 유사도가 계산됩니다. 점수가 가장 높은 카테고리가 문서의 레이블로 지정이 됩니다.

Elasticsearch를 사용한 텍스트 분류

위의 모든 항목은 Elasticsearch(또는 Lucene)를 사용하면 훨씬 간단하게 해결할 수 있습니다.

다음과 같이 4개의 단계만 수행하면 됩니다.

  1. 매핑 구성("content" : "text", "category" : "keyword")
  2. 문서 색인
  3. More Like This 쿼리(MLT 쿼리) 실행
  4. 해당 쿼리의 적중 결과를 점수별로 집계하는 간단한 스크립트 작성
PUT sample
  POST sample/document/_mapping
  {
    "properties":{
       "content":{
          "type":"text",
          "analyzer":"english"
       },
       "category":{
          "type":"text",
          "analyzer":"english",
          "fields":{
             "raw":{
                "type":"keyword"
             }
          }
       }
    }
  }
  POST sample/document/1
  {
    "category":"Apple (Fruit)",
    "content":"Granny Smith, Royal Gala, Golden Delicious and Pink Lady are just a few of the thousands of different kinds of apple that are grown around the world! You can make dried apple rings at home - ask an adult to help you take out the core, thinly slice the apple and bake the rings in the oven at a low heat."
  }
  POST sample/document/2
  {
    "category":"Apple (Company)",
    "content":"Apple is an American multinational technology company headquartered in Cupertino, California, that designs, develops, and sells consumer electronics, computer software, and online services. Its hardware products include the iPhone smartphone, the iPad tablet computer, the Mac personal computer, the iPod portable media player, the Apple Watch smartwatch, and the Apple TV digital media player. Apple's consumer software includes the macOS and iOS operating systems, the iTunes media player, the Safari web browser, and the iLife and iWork creativity and productivity suites. Its online services include the iTunes Store, the iOS App Store and Mac App Store, Apple Music, and iCloud."
  }

MLT 쿼리는 텍스트 마이닝에 매우 중요한 쿼리입니다.

어떻게 작동할까요? 임의 텍스트를 처리하고, 실제 "모델"과 비교하여 상위 n개의 키워드를 추출하고, 이러한 키워드로 부울 매칭 쿼리를 실행할 수 있습니다. 이 쿼리는 종종 유사한 문서를 수집하는 데 사용됩니다.

모든 문서에 클래스/카테고리 레이블이 있고 클래스당 비슷한 수의 훈련 인스턴스가 있는 경우 이는 분류에 해당합니다. 입력 문서를 같은 필드로 사용하여 MLT 쿼리를 실행하고, 상위 n개 적중 결과의 점수 및 카테고리를 집계하는 간단한 스크립트를 작성하기만 하면 됩니다.

GET sample/document/_search
  {
    "query":{
       "more_like_this":{
          "fields":[
             "content",
             "category"
          ],
          "like":"The apple tree (Malus pumila, commonly and erroneously called Malus domestica) is a deciduous tree in the rose family best known for its sweet, pomaceous fruit, the apple. It is cultivated worldwide as a fruit tree, and is the most widely grown species in the genus Malus. The tree originated in Central Asia, where its wild ancestor, Malus sieversii, is still found today. Apples have been grown for thousands of years in Asia and Europe, and were brought to North America by European colonists. Apples have religious and mythological significance in many cultures, including Norse, Greek and European Christian traditions.",
          "min_term_freq":1,
          "max_query_terms":20
       }
    }
  }

이 샘플은 워크플로를 설명하기 위한 것으로, 실제 분류를 위해서는 좀 더 많은 데이터가 필요합니다. 따라서 이 예제에서 실제 결과가 나오지 않더라도 걱정하지 마세요. 더 많은 데이터를 추가하기만 하면 제대로 작동합니다.

다음은 응답을 처리하고 입력 문서에 대해 가장 유력한 카테고리를 반환하는 간단한 Python 스크립트입니다.

from operator import itemgetter
  def get_best_category(response):
     categories = {}
     for hit in response['hits']['hits']:
         score = hit['_score']
         for category in hit['_source']['category']: 
             if category not in categories:
                 categories[category] = score
             else:
                 categories[category] += score
     if len(categories) > 0:
         sortedCategories = sorted(categories.items(), key=itemgetter(1), reverse=True)
         category = sortedCategories[0][0]
     return category

그리고 Elasticsearch 텍스트 분류기가 있습니다!

사용 사례

텍스트 분류는 NLP의 매우 일반적인 실제 사용 사례입니다. 전자 상거래 데이터(제품)를 생각해 보세요. 많은 사람이 제휴 링크로 전자 상거래 상점을 운영합니다. 여러 상점에서 데이터가 제공되고 카테고리 태그가 함께 제공되는 경우도 많습니다. 하지만 각 상점마다 다른 카테고리 태그를 가지고 있습니다. 따라서 카테고리 시스템을 통합해야 하므로 모든 데이터를 새로운 카테고리 트리에 따라 다시 분류해야 합니다. 또는 회사 웹 사이트가 해당 분야(미용실, 빵집 등)에 따라 분류되어야 하는 비즈니스 인텔리전스 애플리케이션을 생각해보세요.

평가

저는 표준 텍스트 분류 데이터 세트: 20 Newsgroups 데이터 세트를 사용하여 이 접근 방식을 평가했습니다. 문서의 12%만 포함하는 고품질 점수 임계값으로 최고 정밀도(92% 정확한 레이블)가 달성되었습니다. 모든 문서에 레이블을 지정할 때(100% 리콜) 예측의 72%가 정확했습니다.

20 Newsgroups 데이터 세트에서 텍스트 분류에 가장 적합한 알고리즘은 일반적으로 SVM 및 Naive Bayes로, 전체 데이터 세트에서 평균 정확도가 더 높습니다.

더 나은 알고리즘이 있는데 분류에 Elasticsearch를 사용해야 하는 이유는 무엇일까요?

몇 가지 실용적인 이유가 있습니다. SVM 모델을 훈련하는 데는 많은 시간이 걸립니다. 특히 스타트업에서 일하거나 다른 고객이나 심각한 문제가 될 수 있는 사용 사례에 빠르게 적용해야 하는 경우에는 더욱더 그렇습니다. 따라서 데이터가 변경될 때마다 모델을 다시 훈련하지 못할 수 있습니다. 저는 대규모 독일 은행 프로젝트를 진행하면서 이를 직접 경험했습니다. 따라서 여러분은 구식 모델로 작업하게 되고 당연히 더는 좋은 성능을 발휘하지 못할 것입니다.

Elasticsearch 접근 방식을 사용하면 인덱스 시간에 훈련이 수행되며 애플리케이션의 가동 중단 없이 언제든지 모델을 동적으로 업데이트할 수 있습니다. 데이터가 Elasticsearch에 저장되어 있으면 추가적인 인프라가 필요하지 않습니다. 대개 10% 이상의 매우 정확한 결과로 첫 페이지를 채울 수 있습니다. 이는 많은 애플리케이션에서 좋은 첫인상을 주기에 충분한 수치입니다.

그렇다면 다른 도구가 있는데도 Elasticsearch를 사용하는 이유는 무엇일까요?

데이터가 Elasticsearch에 이미 존재하고 어쨌든 기본 통계를 미리 계산할 것이기 때문입니다. 이는 거의 NLP를 무료로 사용하는 것과 같습니다!


Saskia Vola

Saskia Vola는 하이델베르크 대학에서 컴퓨터 언어학을 공부했고 2009년에 텍스트 마이닝 분야에서 일하기 시작했습니다. 베를린 스타트업에서 몇 년 동안 근무한 후, 풀타임 프리랜서가 되어 디지털 노마드로서의 삶을 즐기기로 했습니다. 점점 더 많은 관련 프로젝트 제안을 받으면서, textminers.io라는 NLP/AI 프리랜서용 플랫폼을 시작하기로 결정했습니다.