텍스트 마이닝
IT 위키
더 많은 작업
- Text Mining
- 비정형 텍스트에서 패턴, 관계 등을 분석하여 의미있는 정보를 도출해내는 데이터 마이닝 기법
텍스트 마이닝은 문서, 상품평, 뉴스 같은 비정형 데이터를 숫자로 표현한 뒤 통계·기계 학습 기법으로 주제, 감성, 연관 관계를 찾는 분석이다. ADP 필기 4과목 '데이터분석'의 '비정형 데이터 마이닝'은 텍스트 마이닝과 사회연결망 분석으로 구성된다.
- 데이터 마이닝과의 차이
| 구분 | 설명 |
|---|---|
| 데이터 마이닝 | 정량화, 구조화된 데이터에서 원하는 정보를 추출하기 위해 통계적, 기계학습적 알고리즘을 적용 |
| 텍스트 마이닝 | 대량의 비정형 텍스트에 요약, 분류, 군집화 등을 적용하여 새로운 정보 도출 |
- 텍스트 마이닝 기반 기술
| 기법 | 내용 |
|---|---|
| 정보 추출
(Information Extraction) |
|
| 문서 분류
(Classification) |
|
| 문서요약
(Summarization) |
|
- 텍스트 마이닝 응용 기술
| 응용 기술 | 내용 |
|---|---|
| Web Mining | 웹사이트에 텍스트 마이닝 기법을 적용하여 사용자들의 사용성 증대 |
| Concept Linkage | 여러 문서들에서 공유되고 있는 의미를 발견 |
| Question Answering | 사람이 자연어로 질문을 던지면, 문서에서 답을 찾아 제공 |
| Topic Tracking | 사용자 프로필 기반으로 관심있어 할 문서를 추출하여 제공 |
- 수집: 웹 문서, 상품평, 내부 문서 등에서 텍스트를 모은다.
- 코퍼스 구성: 모은 문서를 문서 집합(코퍼스, corpus)으로 묶는다. R tm 패키지의 VCorpus 객체가 이에 해당한다.
- 전처리: 토큰화, 정제, 불용어 제거, 어간 추출이나 형태소 분석으로 분석할 단어만 남긴다.
- 문서 단어 행렬 생성: 문서를 행, 단어를 열(또는 반대)로 두고 빈도나 TF-IDF 가중치를 채운다.
- 분석: 빈도 분석, 연관 단어, 군집·분류, 토픽 모델링, 감성 분석 등을 수행한다.
- 시각화: 워드 클라우드, 단어 연결망 등으로 결과를 보여 준다.
| 작업 | 내용 |
|---|---|
| 토큰화(tokenization) | 문장을 단어 같은 분석 단위(토큰)로 나눈다 |
| 정제 | 대소문자 통일, 문장부호·숫자 제거 |
| 불용어 제거 | 관사, 조사처럼 자주 나오지만 의미 구분에 도움이 안 되는 단어를 뺀다 |
| 어간 추출(stemming) | 규칙에 따라 접사를 잘라 어간만 남긴다(connecting → connect) |
| 표제어 추출(lemmatization) | 사전과 품사 정보로 기본형을 찾는다(was → be) |
| 한국어 형태소 분석 | 한국어는 조사·어미가 붙는 교착어라 띄어쓰기만으로 단어를 나눌 수 없어, 형태소 분석기(파이썬 KoNLPy 등)로 명사 등을 뽑는다 |
| 기법 | 내용 |
|---|---|
| 빈도·TF-IDF | 단어 빈도(TF)에 역문서 빈도(IDF)를 곱해 특정 문서를 잘 드러내는 단어에 큰 가중치를 준다 |
| 연관 단어 | 문서 단어 행렬에서 출현 패턴의 상관이 높은 단어를 찾는다(R tm의 findAssocs) |
| 군집·분류 | 코사인 유사도 등으로 비슷한 문서를 묶거나, 정답이 있는 문서로 분류 모형을 학습한다 |
| 토픽 모델링(LDA) | 잠재 디리클레 할당은 문서를 여러 주제의 혼합으로, 주제를 단어의 확률 분포로 보고 숨은 주제를 추정한다 |
| 감성 분석 | 감성 사전이나 분류 모형으로 문서의 긍정·부정을 판정한다 |
TF-IDF의 기본형은 다음과 같다(은 전체 문서 수, 는 단어 가 나온 문서 수).
library(tm)
library(SnowballC) # stemDocument에 필요
docs <- c("Delivery was fast and the packaging was good.",
"Delivery delayed, packaging damaged!",
"Good price and good quality.",
"Poor quality, I requested a refund.")
corp <- VCorpus(VectorSource(docs))
corp <- tm_map(corp, content_transformer(tolower))
corp <- tm_map(corp, removePunctuation)
corp <- tm_map(corp, removeWords, stopwords("english"))
corp <- tm_map(corp, stemDocument)
tdm <- TermDocumentMatrix(corp) # 단어 x 문서
inspect(tdm)
findFreqTerms(tdm, lowfreq = 2) # 2번 이상 나온 단어
findAssocs(tdm, "qualiti", 0.5) # 상관 0.5 이상인 연관 단어
tdm <- removeSparseTerms(tdm, 0.8) # 희소한 단어 제거
형태소 분석을 마치고 명사만 남겼다고 가정한 문서 4개로 문서 단어 행렬과 TF-IDF를 구한다.
import pandas as pd
from sklearn.feature_extraction.text import CountVectorizer, TfidfVectorizer
docs = ["배송 빠름 포장 만족", "배송 지연 포장 파손",
"가격 만족 품질 만족", "품질 불량 환불 요청"]
cv = CountVectorizer(token_pattern=r"\S+")
dtm = cv.fit_transform(docs)
print(pd.DataFrame(dtm.toarray(), columns=cv.get_feature_names_out()))
tfidf = TfidfVectorizer(token_pattern=r"\S+")
w = pd.Series(tfidf.fit_transform(docs).toarray()[0],
index=tfidf.get_feature_names_out())
print(w[w > 0].round(2)) # 첫 문서의 TF-IDF
실행 결과는 다음과 같다(scikit-learn 1.7.2). scikit-learn은 기본으로 평활 IDF와 L2 정규화를 써서 위 기본식과 값이 다르다.
가격 만족 배송 불량 빠름 요청 지연 파손 포장 품질 환불
0 0 1 1 0 1 0 0 0 1 0 0
1 0 0 1 0 0 0 1 1 1 0 0
2 1 2 0 0 0 0 0 0 0 1 0
3 0 0 0 1 0 1 0 0 0 1 1
만족 0.47
배송 0.47
빠름 0.59
포장 0.47
dtype: float64
첫 문서에서 빈도는 모두 1이지만, 한 문서에만 나온 '빠름'이 두 문서에 나온 '배송'·'포장'·'만족'보다 TF-IDF가 크다.
문서 분류·검색 결과는 정답과 비교해 평가한다(TP: 맞게 찾음, FP: 잘못 찾음, FN: 놓침, TN: 맞게 제외).
| 지표 | 식 | 의미 |
|---|---|---|
| 정확도(accuracy) | 전체 중 맞게 판정한 비율 | |
| 정밀도(precision) | 찾아낸 것 중 맞는 것의 비율. 정확률이라고도 한다 | |
| 재현율(recall) | 찾아야 할 것 중 실제로 찾아낸 비율 | |
| F1 점수 | 정밀도와 재현율의 조화 평균 |
- 처리 절차의 순서와 R tm 패키지 함수(VCorpus, tm_map, TermDocumentMatrix, findFreqTerms, findAssocs, removeSparseTerms)의 역할을 짝지을 수 있어야 한다.
- 불용어 제거, 어간 추출, 표제어 추출의 차이와 한국어에 형태소 분석이 필요한 이유를 묻는다.
- 정밀도와 재현율은 한쪽을 높이면 다른 쪽이 낮아지기 쉬우므로 정의를 혼동하지 않는다.