분석하고싶은코코

NLP - CTM(Contextualized Topic Models) 토픽 모델링 본문

머신러닝&딥러닝/NLP

NLP - CTM(Contextualized Topic Models) 토픽 모델링

코코로코코 2023. 10. 9. 21:43
반응형

토픽 모델링 방법 중 하나인 CTM에 대해서 다뤄보겠습니다.

 

CTM 레퍼런스 : https://contextualized-topic-models.readthedocs.io/en/latest/introduction.html

 

Contextualized Topic Models — Contextualized Topic Models 2.5.0 documentation

Contextualized Topic Models (CTM) are a family of topic models that use pre-trained representations of language (e.g., BERT) to support topic modeling. See the papers for details: Topic Modeling with Contextualized Embeddings Our new topic modeling family

contextualized-topic-models.readthedocs.io

 

Contextualized Topic Models는 문맥을 반영한 모델링을 이야기합니다. 문맥을 반영한 토픽 모델링은 BERT의 문서 임베딩의 표현력과 기존 토픽 모델의 비지도 학습 능력을 결합하여 문서에서 주제(토픽)을 가져오는 모델을 이야기합니다. CTM에서는 Combine-Text-Model과  ZeroShot-Text-Model 두 가지가 있습니다. CobineTM은 상황별 임베딩과 오래된 단어 모음을 결합하여 보다 일관된 주제를 만드는 모델이고, ZeroShotTM은 테스트 데이터에 누락된 단어가 있을 수 있는 작업에 대한 완벽한 주제 모델이라고 소개하고 있습니다.

 

CTM에서 성능에 가장 큰 영향을 주는 것은 전처리라고 소개하고 있습니다. 즉, 다른 단어여도 같은 뜻을 갖는 단어이거나 특수문자가 붙어서 다른 단어로 인식하지 않게 해주는 정규화 작업이 중요하다고 말하고 있습니다. 또한 단어 집합의 크기는 2,000개 이내에서 좋은 성능을 보인다고 설명하고 있습니다. 그래서 기본적인 모듈에서 제공해주는 Vocab크기는 2,000이 default입니다.
 
CTM을 통해서 CombinedTM과 ZeroshotTM을 구현하는 방법은 크게 어렵지 않습니다. 위의 링크한 사이트를 참고하면 잘 설명이 되어있습니다. 기본적으로 CTM의 경우 한국어를 위해서 만들어진 모델이 아니기 때문에 한국어에 맞춘 전처리 작업을 진행해줘야할 필요가 있습니다. 그래서 저는 이번에 Mecab을 사용하여 명사만 추출하여 1글자 이상인 명사들로 전처리를 진행하였습니다. 또한 CTM에서 중요한게 모델의 선택인데 자신이 토픽 모델링을 진행할 언어를 포함하고 있는 베이스 모델을 선택하면 됩니다.
 
제가 사용할 데이터는 깔끔하게 정형화된 데이터라기 보다 특정 게임에 대한 유저들의 리뷰데이터 이기 때문에 ZeroShotTM을 사용했습니다.
from contextualized_topic_models.models.ctm import CombinedTM, ZeroShotTM
from contextualized_topic_models.utils.data_preparation import TopicModelDataPreparation, bert_embeddings_from_list
from contextualized_topic_models.utils.preprocessing import WhiteSpacePreprocessing
from sklearn.feature_extraction.text import CountVectorizer
from konlpy.tag import Mecab
import pandas as pd

df = pd.read_csv('reivews_df_preprocssing_ver.csv')

documents = df['content'].values

b_a_documnets = df[df['app_name']=='블루아카이브']['content'].values

preprocessed_documents = []

for line in tqdm(b_a_documnets):
  # 빈 문자열이거나 숫자로만 이루어진 줄은 제외
  if line and not line.replace(' ', '').isdecimal():
    preprocessed_documents.append(line)
    
class CustomTokenizer:
    def __init__(self, tagger):
        self.tagger = tagger
    def __call__(self, sent):
        word_tokens = self.tagger.nouns(sent)
        result = [word for word in word_tokens if len(word) > 1]
        return result
        
custom_tokenizer = CustomTokenizer(Mecab())

vectorizer = CountVectorizer(tokenizer=custom_tokenizer, max_features=2000)

train_bow_embeddings = vectorizer.fit_transform(preprocessed_documents)
vocab = vectorizer.get_feature_names_out()
id2token = {k: v for k, v in zip(range(0, len(vocab)), vocab)}

MODEL_NAME = "sentence-transformers/xlm-r-100langs-bert-base-nli-stsb-mean-tokens"
train_contextualized_embeddings = bert_embeddings_from_list(preprocessed_documents, MODEL_NAME)

qt = TopicModelDataPreparation()

training_dataset = qt.load(train_contextualized_embeddings, train_bow_embeddings, id2token)


# ctm_combine = CombinedTM(bow_size=len(vocab), contextual_size=768, n_components=10, num_epochs=20)
# ctm_combine.fit(training_dataset)

ctm_zeroshot = ZeroShotTM(bow_size=len(vocab), contextual_size=768, n_components=10, num_epochs = 20)
ctm_zeroshot.fit(training_dataset)

# ctm_combine.get_topics(8)
ctm_zeroshot.get_topics(8)

 

관련 레퍼런스

ZeroShot? - https://velog.io/@nomaday/n-shot-learning

반응형