최근 새로운 자연어 처리라는 새로운 태스크를 접하게 되었습니다. 자연어 처리 과제 중에서도 텍스트에 내포된 감성에 대해 분석하는 과제인 "감성 분석(Sentiment Analysis)"과 "ABSA(Aspect-Based Sentiment Analysis)"에 대해 알아보았고, 간단하게 개념을 정리하기 위해 포스트로 남깁니다.
감성분석
ABSA에 대해 이해하기 위해서는 감성 분석에 대해 먼저 알아야겠습니다. 감성 분석이란, "텍스트에서 감정을 파악하는 자연어 처리(NLP, Natural Language Processing) 과제"입니다. 여기서 얘기하는 "텍스트"는 사람의 의견이 담긴 소비자 리뷰, 설문조사 응답, 채팅 등이 될 수 있습니다. 그 의견이 긍정적인지 부정적인지 혹은 중립적인지를 판단하는 것이죠. 입력은 텍스트이며, 출력은 감정으로 보통 긍정/부정/중립 중 하나로 선택됩니다. 더 세밀한 분류를 위해서는 스케일을 갖는 숫자가 될 수도 있다고 합니다. 예를 들어 1에서 5까지 5점 척도를 갖고 숫자가 커지면 긍정이라고 해석하는 것이죠.
감성 분석은 다양한 곳에서 사용될 수 있습니다. B2C 기업은 마케팅 전략 수립을 위해 감성 분석을 적용합니다. 제품, 서비스에 대한 고객들의 리뷰나 의견을 수집하고 분석하여 어떤 점에 만족하고 불만족하는지를 파악해 이후 제품 개선에 반영하는 것이죠. 고객센터에서 수집된 대화 데이터도 유사한 방식으로 분석하여 제품 개선에 활용하거나, 고객 상담 품질을 향상하는 데에 사용할 수 있습니다. 여론조사에서도 사람들의 의견을 파악하기 위해 감성 분석을 적용할 수 있습니다. 정치, 사회, 경제 등 다양한 분야의 게시글을 분석하여 특정 정당의 지지도를 파악하거나 사회적 이슈에 대한 반응을 분석하여 여론을 파악하는 것이죠. (알아보고 나니, 저의 관심사이면서 곧 다가올 국내 배구 정규 리그인 브이리그에 대해 팬들이 오픈채팅방이나 커뮤니티에 남긴 텍스트를 분석하여 어떤 기대와 감정을 갖고 있을지 분석해보면 재밌겠다는 생각이 드네요. 데이터 수집이 좀 까다롭겠지만요.🤣)
감성 분석은 크게 다음 4단계를 거쳐 진행됩니다.
1. 데이터 수집
감성 분석을 위한 데이터를 수집합니다. 제품에 대한 리뷰나 댓글과 같은 텍스트를 크롤링과 같은 방식을 통해 수집할 수 있습니다. 각 데이터로부터 긍/부정, 중립과 같은 감정을 파악하여 라벨을 부여하는 작업(라벨링)도 포함합니다. 잘 구축된 라벨링 모델이 존재한다면 사람의 손을 거치지 않고 모델 예측 결과를 사용하면 되겠지만 그렇지 않은 경우는 아직 사람의 손이 필요하다고 하네요.
2. 데이터 전처리
수집한 데이터를 정제하고 필요한 형태로 변환합니다. 불용어(Stopwords, 특별한 의미가 없는 단어들 ex. 아, 의, 가, 도, 흐흐 etc)를 제거고 토큰화(Tokenization, 의미를 갖는 토큰로 분리하는 과정)를 수행합니다.
3. 특징 추출
단어의 빈도 수, TF-IDF 점수 등을 사용하여 단어마다 유용한 정보를 추출합니다. 텍스트 그 자체로는 모델에 input으로 넣을 수 없기 때문에 숫자로 변환하는 과정이 필요한 것이죠.
4. 모델 학습 및 예측
텍스트로부터 추출한 특징을 input으로 하여 output인 감성을 예측하는 모델을 학습시킵니다. 학습 이후에는 모델에 텍스트를 넣어서 해당 텍스트가 가진 감성을 예측할 수 있겠습니다.
초기 감성 분석에는 Naive Bayes, SVM과 같이 널리 알려진 기계학습 방법론들을 사용했습니다. 이런 알고리즘들은 문맥 정보를 반영하지 못하기 때문에 성능이 좋지는 않았겠네요. 이후 RNN, LSTM과 같이 시간의 흐름에 따른 정보를 처리할 수 있는 딥러닝 방법론을 사용하였고, 최근에는 Transformer 기반 모델들을 사용하고 있다고 합니다. BERT, GPT와 같이 광범위한 데이터로부터 사전 학습된 언어 모델을 활용하여 감성 분석이라고 하는 downstream 과제를 해결하기 위해 fine-tuning하는 방식이죠.
ABSA
ABSA(Aspect-Based Sentiment Analysis)는 텍스트의 특정 측면(aspect)에 대한 감정 또는 감성을 분석하는 NLP 과제입니다. 예를 들어, "이 카페는 분위기가 좋지만 커피는 맛이 없다"라는 문장에서 '분위기'와 '커피'라는 두 가지 측면에 대해 각각 다른 감성을 분석해주는 것이죠. '분위기' 측면에서는 긍정, '커피' 측면에서는 부정적인 감정을 드러내고 있다는 것을 포착할 수 있습니다.
앞선 감성 분석에서는 텍스트 안에 담겨 있는 여러 가지 측면을 고려하지 못했습니다. 단순한 감성 분석은 "이 카페는 분위기가 좋지만 커피는 맛이 없다"라고 하는 텍스트로부터 "좋다"와 "맛이 없다"라고 하는 대립된 평가를 보고 "중립"이라고 하는 하나의 최종 평가를 내렸겠죠. ABSA는 이와는 다르게 텍스트에 표현된 다양한 관점을 포착할 수 있습니다. 위 텍스트를 보고 하나의 종합적인 평가를 내리는 것이 아니라, '분위기'라고 하는 측면에 대해서는 '좋다'라는 표현을 통해 긍정을, '커피'라고 하는 측면에 대해서는 '맛이 없다'라는 평가를 통해 부정적인 감정을 드러내고 있음을 파악하는 것이죠.
ABSA 수행 절차와 모델
수행 절차
ABSA는 크게 아래와 같이 2단계로 진행됩니다.
1. Aspect Extraction
- 텍스트에서 어떤 측면(Aspect)이 언급되었는지 파악합니다.
- "이 카페는 분위기가 좋지만 커피는 맛이 없다"라고 하는 텍스트에서 '분위기', '커피'라는 측면을 추출합니다.
2. Sentiment Analysis
- 1에서 얻어진 측면에 대해 사용자가 어떤 감성을 표현하였는지를 예측합니다.
- '분위기' 측면은 '좋다'로 '긍정적'이지만, '커피' 측면은 '맛이 없다'로 '부정적'이라고 분류하게 됩니다.
단계에서 확인할 수 있다시피 ABSA 모델의 입력은 자연어 문장이며 output은 (Aspect, Sentiment)입니다. 위 예시 문장 "이 카페는 분위기가 좋지만 커피는 맛이 없다" 이 입력으로 들어가면 모델은 output으로 [(분위기, 긍정), (커피, 부정)] 를 주는 것이죠.
사용 모델
ABSA는 자연어 처리 과제 중 하나로, 번역이나 Q&A, 개체명 인식과 같은 다른 과제들의 발전 역사와 궤를 같이합니다. 과거에는 ABSA를 위해서 규칙 기반 접근을 했다면, 이제는 시퀀스 데이터 처리에 널리 쓰이는 Long Short-Term Memory(LSTM) 네트워크 기반 모델, BERT-based model, Graph Convolutional Networks 을 사용했습니다. 규칙 기반 접근은 미리 정해진 규칙을 갖고 분석을 하지만 복잡한 의미를 갖는 텍스트에 내포된 의미를 파악하기 어렵기 때문에 딥러닝을 적용하기 시작한 것이죠. 대량의 텍스트 데이터로 사전학습된 BERT와 같은 모델들을 기반으로 추가 레이어를 덧붙이거나 파라미터 튜닝을 하는 등 전이 학습을 하면 측면과 감성 분석에 유용한 모델을 학습할 수 있게 됩니다.
데이터셋 소개
[영어] SemEval-2016 Task 5
ABSA 과제를 수행하고 평가하기 위해 대표적으로 사용되는 데이터셋으로는 SemEval-2016이 있습니다. SemEval-2016에는 텍스트의 유사성 판단, 감성 분석, Semantic Parsing과 같은 다양한 자연어처리 과제가 있습니다. Task 5가 바로 ABSA 과제이고, 데이터는 아래 사이트에서 다운로드 받을 수 있습니다. xml 파일이며, python의 내장 라이브러리인 xml으로 쉽게 읽을 수 있습니다.
https://alt.qcri.org/semeval2016/task5/index.php?id=data-and-tools
import pandas as pd
import requests
import xml.etree.ElementTree as ET
# XML URL 설정
xml_url = 'https://alt.qcri.org/semeval2016/task5/data/uploads/trial-data/english-trial/restaurants_trial_english_sl.xml'
# URL로부터 XML 데이터 다운로드
response = requests.get(xml_url)
# XML 데이터 파싱
root = ET.fromstring(response.content)
# 데이터를 저장할 빈 리스트 생성
data = []
# 데이터 추출
for child in root:
for review in child:
for sentence in review.findall('sentence'):
text = sentence.find('text').text
opinions = sentence.find('Opinions')
if opinions is not None:
for opinion in opinions.findall('Opinion'):
target = opinion.get('target')
category = opinion.get('category')
polarity = opinion.get('polarity')
from_pos = opinion.get('from')
to_pos = opinion.get('to')
data.append({'Text': text, 'Target': target, 'Category': category, 'Polarity': polarity, 'From': from_pos, 'To': to_pos})
else:
data.append({'Text': text, 'Target': None, 'Category': None, 'Polarity': None, 'From': None, 'To': None})
# 데이터프레임으로 변환
df = pd.DataFrame(data)
display(df)
위 데이터는 레스토랑 리뷰 데이터 예시인데요, 각 Text가 내포하고 있는 Aspect(Category)와 해당 측면을 표현하고 있는 단어(Target), 측면에 대한 감성(Polarity)을 갖고 있습니다. Category는 위치, 서비스, 음식과 같은 상위 분류와 전반적인 평가, 품질, 가격과 같은 하위 분류의 조합으로 구성되어 있습니다.
예를 들어, " Add to that great service and great food at a reasonable price and you have yourself the beginning of a great evening."(index 2~4) 라고 하는 리뷰에서는 "서비스에 대한 전반적인 평가" 측면에 대해 "긍정적"임을, "음식의 품질과 가격" 측면에서도 "긍정적"임을 확인할 수 있었다는 것이죠.
[한국어] 모두의 말뭉치
ABSA를 위한 한국어 데이터셋도 있는지 찾아보니 국립국어원에서 좋은 자료를 제공해주고 있었습니다. 아래 링크에서 과제 설명을 확인하고 자료를 다운받을 수 있습니다. 자료 다운로드는 회원가입이 필요합니다.
https://corpus.korean.go.kr/taskOrdtm/taskList.do?taskOrdtmId=57&clCd=ING_TASK&subMenuId=sub01
자료는 jsonl 파일로 되어 있으며, 이 파일은 파이썬에서 jsonlines 라이브러리를 사용하여 읽을 수 있어요. 자료를 보면 아래와 같이 문장, [Aspect, [Token, start_position, end_position], Sentiment]로 구성되어 있는 것을 확인할 수 있습니다.
import json
import jsonlines
def read_jsonl(path):
data = list()
with jsonlines.open(path) as f:
for line in f:
data.append(line)
return data
train_data = read_jsonl('./data/absa/nikluge-sa-2022-train.jsonl')
train_data[0]
하나의 문장에도 여러가지 측면이 있을 수 있기 때문에, 3 또는 5가지 측면을 가진 문장들 예시도 확인해보았습니다. 품질, 편의성, 가격 디자인 등 제품에 대한 측면과 함께 각 측면에 대한 사용자의 긍/부정 평가가 라벨링되어 있습니다.
anno_len_list = [len(data['annotation']) for data in train_data]
pretty1 = json.dumps(train_data[anno_len_list.index(3)], indent=4, sort_keys=False, ensure_ascii=False)
pretty2 = json.dumps(train_data[anno_len_list.index(5)], indent=4, sort_keys=False, ensure_ascii=False)
print(pretty1)
print(pretty2)
마치며
지금까지 감성 분석과 ABSA의 개념과 분석 절차, 예시 데이터셋에 대해 알아보았습니다. 텍스트에 담긴 복합적인 감성을 기계가 이해하기가 쉽지는 않겠지만, 학습이 잘 된다면 유용하게 사용될 것 같네요. 일단 개념만 보았을 때는 재미있어 보이는 과제 같아 매우 흥미로웠습니다😏. 다음에 기회가 있다면 모델을 학습하고 예측하는 과정도 포스팅 해보겠습니다. 혹 잘못된 정보가 있다면 댓글로 알려주시면 감사하겠습니다! 🙇♀️
참고
https://wikidocs.net/book/2155
https://monkeylearn.com/sentiment-analysis/
https://monkeylearn.com/blog/aspect-based-sentiment-analysis/
https://blog.naver.com/ys10mjh/222289241258
'繩鋸木斷水滴石穿 > AI | 머신러닝' 카테고리의 다른 글
[IR] Rerank: 검색 결과를 재정렬하여 RAG 성능 높이기 (1) | 2024.07.14 |
---|---|
[NLP] 텍스트 전처리: 파이썬에서 띄어쓰기, 문장 분리 라이브러리 사용하기 (2) | 2023.11.26 |
[Tips] 범주형 변수의 카테고리 개수를 줄이는 방법들 (1) | 2023.09.10 |
[sklearn] LabelEncoder와 OrdinalEncoder 비교 (0) | 2023.08.27 |
[모니터링] 2) 드리프트 감지 방법: KS 검정과 PSI (1) | 2023.05.28 |