ABSA와 Doc2Vec으로 의견 맥락을 분석하는 텍스트 마이닝
ABSA와 Doc2Vec을 결합해 속성별 감성과 문서 맥락을 함께 분석하는 텍스트 마이닝 파이프라인의 구성과 운영 기준
2026-08-14 · 최초 발행 2024-04-29
속성별 의견과 문서 맥락을 함께 읽는 방법
제품 리뷰, 콜센터 녹취, 커뮤니티 게시글에는 긍정과 부정이 한 문장에 섞여 있는 경우가 많다. “배터리 수명은 길지만 화면은 어둡다”라는 문장에서 배터리에는 긍정, 화면에는 부정이 연결된다. 문서 전체를 하나의 감성으로만 분류하면 이런 차이를 잃는다.
Aspect-Based Sentiment Analysis(ABSA)는 문장 또는 문서에서 특정 속성(Aspect)을 찾아 그 단위의 감성 극성을 추정하는 기법이다. Doc2Vec은 문서 전체의 의미를 고정 길이 벡터로 학습하는 분산 표현 기법이며, PV-DM(Distributed Memory)과 PV-DBOW(Distributed Bag of Words)를 주요 변형으로 둔다.
두 방식을 결합하면 ABSA가 제공하는 미시적 의견 신호와 Doc2Vec의 문서 컨텍스트를 함께 다룰 수 있다. 요약, 분류, 추천 같은 다운스트림 태스크에서 성능과 해석 가능성을 동시에 확보하는 것이 목적이다.
분석 파이프라인에서 다루는 요소
ABSA는 전처리와 문장 분할 뒤 형태소 분석 또는 품사 태깅을 적용하는 흐름으로 시작한다. Aspect는 의존 구문이나 명사구를 이용한 룰 기반 방식으로 찾을 수 있고, BiLSTM-CRF 또는 Transformer 기반의 지도학습·신경망 모델로 추출할 수도 있다. 감성 분류는 lexicon 기반이거나 미세조정된 언어모델을 이용한 이원·다중분류로 구성한다.
Doc2Vec의 PV-DM은 문서 벡터와 주변 단어 컨텍스트를 사용해 중심 단어를 예측하므로 컨텍스트에 민감한 표현을 강화한다. PV-DBOW는 문서 벡터로 문서의 단어를 예측해 계산량과 확장성 측면에서 다른 선택지를 제공한다. 신규 문서는 학습된 모델의 infer_vector로 임베딩을 추론한다.
라벨링은 문장 단위로 수행하고 Aspect 사전(seed lexicon) 및 SOC(Subject-Opinion-Context) 스키마를 활용할 수 있다. 중립·혼합 감성과 모호한 표현의 처리 기준을 문서화해야 하며, 액티브 러닝을 통해 라벨링 비용과 품질의 균형을 맞춘다.
운영 단계에서는 모델 레지스트리와 버전 관리로 데이터·코드·파라미터의 불변성을 보장한다. 추론 지연 시간은 캐시와 배치 추론을 혼용해 관리하고, 학습과 추론 결과가 어긋나지 않도록 토크나이저와 전처리를 분리·고정할 필요가 있다.
입력부터 다운스트림 연계까지의 흐름
입력은 리뷰·콜로그·게시글 같은 텍스트와 제품·채널·시간 등의 메타데이터다. 정제, 문장 분할, 토큰화, 품사 태깅을 거친 뒤 Aspect를 추출하고, Aspect-Context 윈도우에 분류기를 적용해 감성을 판별한다. 동시에 Doc2Vec PV-DM 또는 PV-DBOW를 학습하고 infer_vector로 문서 임베딩을 만든다.
Aspect 감성 점수와 문서 벡터를 결합한 피처는 다운스트림 모델의 입력이 된다. 결과는 Aspect-감성 테이블, 문서 임베딩, 대시보드·알림·추천 시스템 연계 결과로 사용할 수 있다.
품질 관리는 Aspect 추출 F1, 감성 분류 macro-F1, 임베딩 유사도 안정성 지표로 수행한다. OOV 단어율 상한과 비한국어 비율 임계치를 넘는 샘플은 제외하고 재수집하며, 랜덤 시드와 토크나이저 버전을 고정하고 모델 아티팩트 해시를 검증해 재현성을 관리한다.
PV-DM과 PV-DBOW를 고르는 기준
| 항목 | PV-DM | PV-DBOW |
|---|---|---|
| 성능 | 문맥 반영 우수, 의미 보존력 높음 | 짧은 문서 다량 처리에 유리 |
| 확장성 | 상대적으로 느림, 메모리 사용량 큼 | 빠름, 대규모 말뭉치 처리 용이 |
| 일관성 | 컨텍스트 윈도우 민감, 튜닝 필요 | 파라미터 민감도 낮음 |
| 안정성 | 데이터 노이즈에 다소 취약 | 노이즈 영향 상대적 낮음 |
| 운영 편의 | 추론 비용 높음 | 추론 단순, 서비스 편의성 높음 |
파이프라인 코드 예시
전제조건은 Python 3.10, gensim 4.3.2, scikit-learn 1.4.*, KoNLPy 0.6.0, JPype1 설치다. 한국어 형태소 분석기로는 Okt를 기본 사용하며, 프로덕션에서는 MeCab-ko를 권장한다. 아래 데모 데이터는 예시 리스트이므로 실제 적용 시에는 사내 데이터를 적재한다.
# pip install gensim==4.3.2 scikit-learn==1.4.2 konlpy==0.6.0 JPype1==1.5.0
from gensim.models.doc2vec import Doc2Vec, TaggedDocument
from konlpy.tag import Okt
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.linear_model import LogisticRegression
from sklearn.pipeline import FeatureUnion
from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_report
import numpy as np
# 1) 데이터 준비 (toy)
docs = [
"배터리 수명은 길고 화면 밝기는 낮다",
"카메라 화질이 뛰어나지만 발열이 심하다",
"디자인이 예쁘고 성능도 만족스럽다",
"가격이 비싸고 고객 지원이 불만족스럽다",
]
# Aspect 라벨 예시: (문서, [(aspect, 문장스팬, 라벨)])
aspect_labels = [
[("배터리", "긍정"), ("화면", "부정")],
[("카메라", "긍정"), ("발열", "부정")],
[("디자인", "긍정"), ("성능", "긍정")],
[("가격", "부정"), ("고객 지원", "부정")],
]
okt = Okt()
def tokenize(sent):
return [w for w, t in okt.pos(sent, stem=True) if t.startswith("N") or t.startswith("A")]
# 2) Doc2Vec 학습
tagged = [TaggedDocument(tokenize(d), [i]) for i, d in enumerate(docs)]
d2v = Doc2Vec(vector_size=64, window=5, min_count=1, workers=2, dm=1, epochs=40, seed=42)
d2v.build_vocab(tagged)
d2v.train(tagged, total_examples=d2v.corpus_count, epochs=d2v.epochs)
# 3) Aspect 추출(단순 명사구 룰) 및 감성 분류용 데이터 구성
# 실제 환경: 의존구문/시퀀스 라벨링 모델 대체 권장
X_text, X_doc, y = [], [], []
for i, d in enumerate(docs):
tokens = tokenize(d)
text = " ".join(tokens)
for asp, label in aspect_labels[i]:
# Aspect 주변 컨텍스트 윈도우 구성(단순 포함 룰)
if asp.replace(" ", "") in d.replace(" ", ""):
X_text.append(text)
X_doc.append(d2v.infer_vector(tokens, epochs=20))
y.append(1 if label == "긍정" else 0)
# 4) 피처 결합: BoW + Doc2Vec
cv = CountVectorizer(min_df=1)
X_bow = cv.fit_transform(X_text)
X_doc = np.vstack(X_doc)
# 희소 + 밀집 결합
from scipy.sparse import hstack, csr_matrix
X = hstack([X_bow, csr_matrix(X_doc)])
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.5, random_state=42, stratify=y)
clf = LogisticRegression(max_iter=1000, n_jobs=1)
clf.fit(X_train, y_train)
pred = clf.predict(X_test)
print(classification_report(y_test, pred, target_names=["부정","긍정"]))
예시에서는 Aspect를 단순 명사구 규칙으로 찾지만, 실제 환경에서는 의존 구문 기반 규칙 또는 BiLSTM-CRF·Transformer 토크나이저 출력과 결합하는 방식을 권장한다. Doc2Vec은 PV-DM(dm=1) 설정을 사용했으며, 대규모 코퍼스에서는 PV-DBOW(dm=0)와 더 큰 negative sampling 조합을 고려할 수 있다. 불균형 대응에는 교차 검증, macro-F1, class-weight 적용이 필요하다.
한국어 사전 기반 감성 분류기와 사전은 도메인별 최신 어휘 업데이트가 필요하다. GPU 환경에서 Transformer 기반 ABSA를 미세조정할 때는 라이브러리 버전 호환성도 검증해야 한다.
업무 데이터에서의 활용 방식
전자상거래 리뷰 분석에서는 상품 리뷰와 카테고리·모델 메타데이터를 입력으로 받는다. 카테고리별 Aspect 사전 시드를 확장하고 ABSA와 Doc2Vec 융합 분류를 적용해 주간 리포팅을 자동화할 수 있다. 제품별 상위 불만 요인, 개선 우선순위 리스트, A/B 개선 효과 추적이 결과물이다.
금융 콜센터 민원 분석에서는 STT 전사 텍스트와 통화 메타데이터를 사용한다. 화자 분리 뒤 문장화하고, 컴플라이언스 관련 Aspect 중심의 사전과 위험 신호 스코어링을 적용한다. 리스크 얼럿, 스크립트 개선 포인트, 상담 품질 지표의 상관분석으로 이어진다.
SaaS 앱스토어 피드백 운영에서는 리뷰와 별점, 릴리스 노트를 함께 다룬다. 릴리스 버전을 기준으로 전후를 비교하고 Aspect별 감성 드리프트를 탐지해 기능별 만족도 트렌드, 백로그 우선순위, 자동 릴리스 노트 요약을 제공한다.
해석 가능성과 라벨링 비용에 미치는 영향
단순 문서 감성 분석과 비교하면 Aspect 정밀도를 높여 해석 가능성을 개선할 수 있으며, 고객 VOC 분류 F1은 +512%p를 기대할 수 있다. 문서 임베딩을 융합하면 콜드스타트를 완화해 신제품 초기 리뷰 분류 정확도를 +37%p 개선할 수 있다. 반자동 라벨링과 액티브 러닝을 도입하면 라벨 비용은 20~40% 절감된다.
원인과 대응의 연결성이 강해져 개선 과제 도출 속도가 높아지고, 대시보드의 일관된 지표는 조직 간 합의 비용을 줄인다. 드리프트에 따른 모델 성능 저하를 조기에 감지하면서 지속적인 개선 체계를 운영할 수 있다.
ABSA는 의견이 향하는 대상을 분리하고, Doc2Vec은 그 의견이 놓인 문서 맥락을 보완한다. 도메인 사전 확장, 액티브 러닝, PV-DBOW 병행과 Transformer ABSA를 함께 검토하면서 버전·재현성·모니터링 체계를 파이프라인에 포함하는 구성이 적합하다.