본문 바로가기

초보가 쓰는 초보를 위한, 연구 코딩 리뷰

BERTopic 이란? 예제 코드로 살펴보는 최첨단 토픽모델링(한국어 데이터에 적용)

#필요 라이브러리
import pandas as pd
import re
from bertopic import BERTopic

BERTopic 이란? (참조 https://github.com/MaartenGr/BERTopic)

토픽모델링은 문서 집합에서 토픽을 추출해내는 방법이다. BERTopic은 최첨단 토픽모델링 방법 중 하나이다. 기존의 토픽모델링은 같은 문서 안에 있는 단어들을 유사하다고 판단하는 bag-of-words 기반 토픽모델링이었다. 반면, BERTopic은 각 단어의 특징과 유사도를 나타내 주는 학습 임베딩 기법을 사용한다. 학습 기반 임베딩 기법 중에서도, 성능이 매우 뛰어난 BERT 모델을 활용하여 기존 bag-of-words기반 토픽모델링보다 맥락을 반영한 토픽 추출에 유리하다. 

또한, BERTopic 을 만들어 주신 연구자분께서 이론적 기반 코딩 이해도가 조금 부족하더라도 편하게 사용할 수 있도록, 사용자 친화적으로 개발해놓으셨다. 위에 github링크를 통해 학습한다면, 2시간 내외로 필요한 기능을 익힐 수 있을 것이다.

 

 

예제 데이터

BERTopic을 사용하여, '최저임금'을 둘러싼 최근 뉴스 주제들이 어떤 양상을 띄는지 살펴보았다.

데이터는 빅카인즈(한국언론진흥재단)에서 '최저임금'을 단어를 포함한 뉴스를(기간 2018~2021) 수집하였다. https://www.bigkinds.or.kr/

 

빅카인즈(BIG KINDS)

뉴스빅데이터 분석시스템, 뉴스 속 키워드 관계망, 주요 이슈, 정보원, 이슈 트렌드 분석 정보 제공

www.bigkinds.or.kr

위의 링크는 빅카인즈 링크이다. 빅카인즈는 사용자 친화적인 데이터 분석환경을 제공하는 것 같다! 개인적으로는 매우 만족하며 사용중 이다! 사회 과학 분야 연구나 뉴스 분야에 관심이 있는 연구자라면 참고하면 도움이 되리라 생각한다.

 

뉴스 데이터에서는 매우 많은 column 정보를 제공하지만, 이번 분석에서는 뉴스 생성일자와 뉴스 본문의 키워드를 분석에 사용한다. 

데이터 형태는 다음과 같다.

여기서 키워드 항목은, 본문 내에서 추출된 키워드 중 단순 숫자(1, 2, 2018, 2019 등), 이메일 주소, 시간을 뜻하는 단어(밤, 낮, 새벽 등)를 제외한 결과라고 한다. 키워드 열은 분석에 사용되는 전처리 load를 줄여준다. 형태소 단위의 전처리를 거쳐 키워드가 선별되기 때문에, 다른 언어들에 비해 상대적으로 복잡한 한국어 전처리 과정을 거치지 않고 본문을 분석할 수 있다는 장점이 있다. 또한, 본문 내용 중 중요 단어들만 뽑아 놓았기 때문에 전체 본문을 사용할 때 대비 데이터 크기를 줄일 수 있다.

 

데이터 전처리

BERTopic은 BERT 모델을 사용한다. 전처리에서 중요한 점은, BERT이 문장을 input으로 받는 다는 점이다. 따라서, BERTopic 사용시에도, 문장 형식의 input이 필요하다. 키워드 열의 string 데이터는 현재 ,를 구분자로 사용한 단어들의 나열이다. 문장 형식을 흉내내기 위해 "," 를 띄어쓰기로 바꿔준다. ex) 박용만, 회장, 작심 => 박용만 회장 작심

#pip install re  라이브러리 없을 시 실행
import re #replace 함수를 갖고 있는 전처리에 유용한 라이브러리입니다. 
df.sentence = df.apply(lambda row: re.sub(",", " ", row.키워드).lower(), 1) #문장형태로 바뀐 문장들을 sentence 열에 할당합니다.
sentence_list = df.sentence.to_list() #토픽모델링을 진행하기 전에, sentence열을 list 타입으로 바꾸어 sentence_list에 할당합니다.

전처리 결과물

 

토픽모델링 - GPU 서버를 이용하시거나 colab에서 GPU 설정을 완료하신 후 아래 코드를 실행하시는 것이 좋습니다.(컴퓨팅 파워가 많이 듭니다.)

BERTopic은 BERT embedding을 사용하고, default로 사용하는 BERT모델은 50가지 이상의 언어를 지원하며, 한국어도 포함된다.

아래는 한국어로 pre-trained된 BERT모델을 불러와, 우리 데이터에 적용할 모델을 만드는 과정이다. BERTopic은 n_gram단위의 토픽 단어 추출도 지원한다. n_gram_range 파라미터를 조정하여 n_gram의 범위를 조정할 수 있다. e.g.) 1~2 gram은 (1,2), 2개의 연속된 단어들만 보고 싶다면, n_gram_range = (2,2)로 설정할 수 있다.

topic_model = BERTopic(language= 'korean', min_topic_size = 50, verbose= True, n_gram_range=(2,2)) #한국어로 pretrained 된 transformer 모델을 불러옵니다. 
#min topic size의 default는 10이지만, 지나치게 많은 topic 수가 나오는 것을 방지하기 위해 50 수정하였다. 숫자가 커지면 해석해야할 topic수가 줄어든다.

 

위에서 만든 모델을, 앞서 전처리한 데이터에 적용하여 토픽을 추출하는 코드이다. topics에는 추출된 토픽 번호가 할당된다.

topics, _ = topic_model.fit_transform(sentence_list) #우리 데이터에 transfomer 모델을 적용한하여 topic을 추출합니다. GPU서버 이용 권장

 

토픽확인

 

90개이상의 토픽이 뽑혔음을 확인할 수 있다. 그 중 topic 안에 속하는 기사들의 숫자가 많은 순으로 20개의 토픽들을 추출하였다. -1 Topic은 noise이다. 

열설명: Topic은 추출된 토픽의 번호(이름)이다. Count는 해당 토픽에 속하는 문서의 수(여기선 기사의 수)이다. Name은 해당 Topic을 대표할 수 있든 단어들이다. 앞서 있는 단어가 더 대표성이 높다고 계산된 단어들이다.(c-tf-idf 기준). Name열을 통해, 해당 토픽이 어떤 토픽인지 사람이 대락적으로 유추해낼 수 있다.

#뽑아낸 토픽을 확인합니다. Topic -1 noise토픽입니다. 
print(set(topics))
freq = topic_model.get_topic_info(); freq.head(20)

코드 실행 결과물

90개가 넘는 토픽이 추출되었다. 90개가 넘는 토픽은 사람이 해석하는 데 시간이 많이 소요되므로, 토픽의 개수를 줄이기로 결정하였다.

 

토픽 개수 줄이기 - 너무 많은 토픽이 뽑힌 경우, 시행합니다.

 

아래코드는 토픽의 개수를 줄이는 코드이다. nr_topics 를 'auto'로 설정한다면, 모든 토픽들 간 코사인 유사도가 0.9 미만이 될 때까지 작은 토픽들을 좀 더 큰 사이즈의 토픽(개수기준)으로 병합시킨다. 원하는 토픽 수가 있다면, nr_topics에 특정 숫자를 할당할 수 있다. e.g) nr_topics = 12 는 12개의 토픽을 추출해준다.

new_topics, new_probs = topic_model.reduce_topics(sentence_list, topics, _, nr_topics= 'auto')

토픽들간의 거리를 확인할 수 있는 시각화 기능도 제공한다.

topic_model.visualize_topics()

토픽별로 대표단어를 시각화를 통해, 확인하고 싶을 땐 아래코드가 효과적인 것 같다.

topic_model.visualize_barchart(top_n_topics=8)

 

이 포스트에서는, BERTopic에 대한 기본 사용법을 다뤘다. 

BERTopic은 기본 기능 외에 커스터마이징, Dynamic Topic Modeling등 다양한 기능을 제공한다.  아래 링크를 참고하여, 공부해볼 것을 추천한다. 

https://github.com/MaartenGr/BERTopic