LDA, Latent Dirichlet Allocation
Woonn
2020-05-21
1. LDA란?
1.1 LDA의 정의 및 가정
Latent Dirichlet Allocation(잠재 디리클레 할당)
이란 텍스트마이닝의 방법중 하나업니다. 텍스트를 DTM(Document-Term Matrix)
으로 만들어 단어의 등장 빈도에 따라 텍스트를 분류합니다. 단어가 모이면 문장을 이루고 문장이 모이면 문서를 이루게 됩니다. 그릭고 문서, 문장 안에서도 서로 묶이는 단어들이 있습니다. 이를 바탕으로 문서 전체를 분석하여 단어끼리의 경향성을 계산하고, 그 문서를 대표하는 특정 토픽을 찾아내는 것, 그것이 LDA의 목적입니다.
LDA에는 몇 가지 가정이 있는데 그 중 중요한 것은 단어의 교환성(exchangeability)
입니다. 교환성
이란 단어들의 순서는 상관하지 않고 오로지 단어들의 유무만이 중요하다는 가정입니다. 예를 들면, ‘나는 전설이다’ 라는 문장과 ’전설은 나다’라는 문장은 ’나’와 ’전설’이 한번씩 나오므로 서로간에 차이는 없다고 봅니다. 이 가정을 기반으로 단어와 문서들의 교환성을 포함하는 혼합 모형을 제시한 것이 바로 LDA입니다.
1.2 LDA의 주제
LDA
에서 각각의 문서는 여러개의 주제를 가지고 있습니다. 확률 잠재 의미 분석 (Probabilistic latent semantic analysis, pLSA)
과 비슷하지만 주제들이 디리클레 분포를 따른다고 가정합니다. 예를 들어 [양자역학, 공유결합, 슈뢰딩거 파동방정식]
등의 단어가 자주 등장하는 문서와 [감자, 오발탄, 소나기, 봄봄]
등의 단어가 많이 쓰인 문서가 있다고 가정합시다. 왠지 고등학교 비문학 시간에 많이 본 듯 합니다. 이때 우리는 해당 문서가 물리학, 문학에 관련된 내용이라고 추측할 수 있습니다. 그 이유는 우리는 문서에 들어가 있는 단어들이 해당 해당 주제들을 표현하고 있음을 알기 때문입니다. 일반적으로 사전 정보가 없다면 주제를 예측하기는 어렵습니다. 하지만 단어들과 주제들은 연관성이 있습니다. 주제는 의미나 인식으로 결정되는 것이 아니고, 지도 학습으로 라벨링된 단어들의 가능도로 결정합니다.
LDA의 결과물을 해석하는 것은 분석가의 역량입니다. 따라서 분석하려는 문서에 대한 일정수준 이상의 배경지식이나 사전 정보가 요구됩니다.
2. LDA 실습
2.1 LDA 패키지
lubridate
는 손쉽게 character 형식을 date 형식으로 바꿔주는 패키지입니다. tm
은 text mining을 위한 패키지고, topicmodels
가 LDA 분석 함수를 포함합니다.
library(stringr)
library(tidyverse)
library(tidytext)
library(KoNLP)
library(ggplot2)
library(lubridate)
library(tm)
library(topicmodels)
library(readr)
library(dplyr)
library(stringr)
library(readxl)
useSejongDic()
## Backup was just finished!
## 370957 words dictionary was built.
## Backup was just finished!
## 983012 words dictionary was built.
2.2 데이터 불러오기
분석에 활용할 데이터는 관광
을 키워드로 중앙지로 분류된 11개 신문사(경향신문, 국민일보, 내일신문, 동아일보, 문화일보, 서울신문, 세계일보, 조선일보, 중앙일보, 한겨례, 한국일보)의 기사 5,547건입니다. 코로나가 처음 보고된 2020년 01월 08일부터 2020년 03월 31일까지의 기사를 바탕으로 코로나가 관광에 끼친 영향이 나타나는지 분석해 보겠습니다.
tour <- read_xlsx("관광기사(0108_0331).xlsx")
colnames(tour)[17] <- c("contents")#컬럼명이 한글일 경우 에러가 발생하기도 함
tour$contents <- iconv(tour$contents, "utf8", "UTF-8")
2.3 전처리
분석에 불필요한 특수문자, 한자, 공백 등을 제거합니다.
tour$contents <- str_replace_all(tour$contents, pattern="\r", replacement="") %>%
#str_replace_all(pattern="\t", replacement=" ") %>%
str_replace_all(pattern="\n", replacement=" ") %>%
str_replace_all(pattern="[\u3000]", replacement=" ") %>%
str_replace_all(pattern="[ ]{2}", replacement="") %>%
str_replace_all(pattern="[[:punct:]]", replacement=" ") %>%
str_replace_all(pattern="[\u4E00-\u9FD5○]", replacement="") %>%
str_replace_all(pattern="현지시간", replacement="") %>%
str_replace_all(pattern="연합뉴스", replacement="") %>% #기사 첫머리에 붙는 단어로 제거
#str_replace_all(pattern="코로나바이러스", replacement="") %>% #너무 많아 다른 단어가 묻힘
str_replace_all(pattern="순위종목명등락률연관", replacement="") %>%
str_replace_all(pattern="이다해당", replacement="") %>% # 불명확한 단어로 제거
str_replace_all(pattern=" ", replacement=" ")
head(tour$contents)
## [1] "지난 29일 서울 용산구 용산전자상가에 위치한 전자랜드 상가 내부가 손님들의 발길이 뜸한 가운데 한산한 모습을 보이고 있다 이우중 기자 당장 밖을 보세요 사람이 있나 지나가는 사람이 있어야 물건을 살 사람도 있죠 지난 29일 찾은 서울 용산구 용산전자상가는 휑하다 못해 적막감마저 들었다 주말이라 일부 상가 건물이 문을 닫는다는 "
## [2] "서울 강남구 삼성역 일대가 대기업 계열 호텔의 격전지로 떠오르고 있다 지에스 GS 그룹 에이치디씨 HDC 그룹에 이어 삼성그룹까지 가세하면서 비즈니스 고객을 사로잡기 위한 경쟁이 치열해질 것으로 보인다 호텔신라는 4월1일부터 삼성역 인근에 비즈니스호텔인 신라스테이 삼성 의 영업을 개시한다고 31일 밝혔다 지하 3층~지상 21층 건물에 총 30 "
## [3] "영국에서 입국한 2명이 광주광역시에서 신종 코로나바이러스 감염증 코로나19 확진 판정을 받았다 2명의 추가 확진자들은 전용 공항버스와 KTX를 이용해 광주로 이동했다 31일 광주시에 따르면 지난 29일 영국에서 입국한 2명이 코로나19 진단검사에서 양성 판정을 받았다 광주 21번째 확진자 A씨 43 여 와 22번째 확진자 B씨 20 여 "
## [4] "외교부가 1989년도 생산된 외교 문서의 기밀을 해제하면서 그해 세간을 떠들썩하게 했던 임수경 무단 방북 사건 관련 문서는 비공개해 논란이 일고 있다 31일 외교부는 총 1577권 23만 6900여 쪽 분량의 외교 문서의 기밀을 해제했다 그런데 그해 언론의 이목이 쏠렸던 임수경씨 방북 사건 관련 문서는 정작 극히 일부만 포함됐다 임 "
## [5] "오늘 코스피 시장에서 외국인이 많이 순매도한 종목은 삼성전자우 005935 KODEX 200 SK텔레콤 017670 삼성전자 005930 S Oil 010950 등이다 금액 억원 순위종목명금액주가 등락률연관 섹터1삼성전자우 005935 297 33 0 87 반도체와 반도체 장비2KODEX 200262 89+1 77 코스피 상승에 "
## [6] "오늘 코스닥 시장에서 외국인이 많이 순매도한 종목은 씨젠 096530 아난티 025980 고영 098460 케이엠더블유 032500 대아티아이 045390 등이다 금액 억원 순위종목명금액주가 등락률연관 섹터1씨젠 096530 192 86 8 18 유전체검사 2아난티 025980 67 93+29 95 금강산 관광 3고영 098 "
한글을 분석하는 다양한 패키지가 존재하지만, 복잡한 탓에 분리를 잘못하거나 오타 등으로 제대로 된 분석이 어려울 수 있습니다. 따라서 보다 정확한 결과를 얻기 위해 불용어 사전을 만들고 분석하려는 문서에서 삭제해줍니다.
stopWords <- read_lines("stopword.txt")
stopWords <- unique(stopWords) # 중복제거
stopWords <- gsub("\uFEFF", "", stopWords)
for(i in seq_along(stopWords)) {
tour$contents <- stringr::str_replace_all(tour$contents, fixed(stopWords)," ")
}
KoNLP
의 SimplePos22()
함수를 통해 형태소 분석을 한 뒤, 체언과 용언 만을 추출합니다.
ko_words <- function(doc){
pos <- str_split(doc,";")## 띄어쓰기(' ')를 기준으로 한 문장을 여러 단어로 나눔
pos <- paste(SimplePos22(pos))
extracted <- str_match(pos, "([가-힣a-zA-Z]+)/[NC]")#명사,동사, 형용사 동시에 가져옴
keyword <- extracted[,2]
keyword[!is.na(keyword)]
}
2.4 TDM
전처리가 끝난 데이터를 바탕으로 형태소 분석을 한 데이터를 corpus
로 만든 다음, TDM
형태로 만들어 줍니다. 이때 2글자 이상, 10글자 이하만 사용하여 의미 없는 단어를 제거해주도록 하겠습니다.
options(mc.cores=1)
myCorpus<- VCorpus(VectorSource(tour$contents))
tour_tdm <- TermDocumentMatrix(myCorpus,
control=list(tokenize=ko_words,
removePunctuation=T,
removeNumbers=T,
wordLengths=c(2, 10)))
nTerms
는 추출한 단어의 수, nDocs
는 추출한 문서의 수를 보여줍니다. head()
로 어떤 단어들이 추출되었는지 확인합니다.
## [1] 26485
## [1] 5547
## [1] "afp" "ap" "ap통신에" "asisa" "ch" "cj"
분석에 0 또는 등장하지 않는 term은 불필요한 작업을 늘려줄 뿐으로 작업시간을 연장시킬 뿐입니다. 따라서 쓸모없는 빈칸은 제거하고, 단어별 빈도를 측정하여 wordFreq라는 변수로 만들어 줍니다.
tour_tdm <- removeSparseTerms(tour_tdm, sparse = 0.99)
wordFreq <- slam::row_sums(tour_tdm)
wordFreq <- sort(wordFreq,decreasing=TRUE)
2.5 DTM
TDM
형식을 DTM
형식으로 바꿔줍니다.
dtm <- as.DocumentTermMatrix(tour_tdm)
rowTotals <- apply(dtm , 1, sum) #문서별 단어의 수를 구함
dtm.new <- dtm[rowTotals> 0, ]
dtm <- dtm.new
2.6 LDA
topicmodels
의 LDA함수를 이용하여 텍스트를 분류합니다. k는 나눌 집단의 수입니다. 6개의 집단으로 나눠 보겠습니다.
## Topic 1 Topic 2 Topic 3 Topic 4 Topic 5
## [1,] "시장" "지원" "북한" "올해" "신종"
## [2,] "외국" "테마" "미국" "관광" "감염증"
## [3,] "종목" "기업" "대통령" "지역" "코로나바이러스"
## [4,] "자료" "국회" "정부" "사업" "정부"
## [5,] "외국계" "대표" "문재인" "관광객" "확산"
## [6,] "오전" "서울" "남북" "지난해" "사태"
## [7,] "서울시" "규모" "청와대" "세계" "중국"
## [8,] "해당" "운영" "개별관광" "대구" "경제"
## [9,] "코스닥" "예정" "추진" "선정" "입국"
## [10,] "상위" "지정" "관광" "도시" "조치"
## [11,] "오후" "대비" "해리스" "경북" "대응"
## [12,] "코스피" "마스크" "이날" "부산" "한국"
## [13,] "실제" "국내" "우리" "주요" "상황"
## [14,] "영화" "서비스" "한국" "추진" "일본"
## [15,] "개사" "지난해" "대사" "문화체육관광부" "대책"
## [16,] "기록" "경기도" "대북" "축제" "중단"
## [17,] "수치" "진행" "국무부" "전남" "영향"
## [18,] "오늘" "충남" "협력" "한국" "이날"
## [19,] "순수한" "일정" "제재" "전국" "바이러스"
## [20,] "증권사" "의원" "문제" "조성" "세계"
## Topic 6
## [1,] "우한"
## [2,] "중국"
## [3,] "신종"
## [4,] "코로나바이러스"
## [5,] "확진자"
## [6,] "폐렴"
## [7,] "감염증"
## [8,] "중국인"
## [9,] "환자"
## [10,] "제주"
## [11,] "확진"
## [12,] "국내"
## [13,] "번째"
## [14,] "감염"
## [15,] "확인"
## [16,] "지난달"
## [17,] "제주도"
## [18,] "관광객"
## [19,] "판정"
## [20,] "방문"
## Length Class Mode
## 1 LDA_VEM S4
그리고 이를 그래프로 그려보겠습니다.
x <- posterior(lda)$terms # $terms와 $topics를 인덱싱할 수 있음
y <- data.frame(t(x[,apply(x,2,max)>0.03]))
z <- data.frame(type=paste("Topic", 1),
keyword=rownames(y), posterior=y[,1])
for (i in 2:6) {
z <- rbind(z, data.frame(type=paste("Topic",i),
keyword=rownames(y), posterior=y[,i]))
}
ggplot(z,aes(keyword,posterior, fill=as.factor(keyword)))+
geom_bar(position = "dodge", stat = "identity")+
coord_flip()+
facet_wrap(~type,nrow = 1) +
theme(legend.position = "none")
3. 해석
해당 그래프를 바탕으로 단어 모음별 토픽을 판단합니다. 저는 이 그래프를 1.경제, 2.사회, 3.국제/정치, 4.문화, 5.진보, 6.보수 신문으로 구분했습니다.
- 토픽 1은 코스피, 코스닥, 종목, 자료, 외국계, 외국, 오후, 오전 등의 단어들로 미루어보아
경제신문
이라는것을 알 수 있습니다.
- 토픽 2는 테마, 지원, 지역, 관광 등이 작은 수치로 나타나 있습니다. 이는
사회신문
으로 보입니다.
- 토픽 3은 정부, 북한, 미국, 문재인, 대통령, 관광이 주된 키워드입니다. 이는
국제/정치신문
으로 보입니다.
- 토픽 4는 지역과 관광이라는 키워드가 가장 높은 문서입니다. 이는
문화신문
일 가능성이 높습니다.
5번, 6번은 함께 묶어서 보도록 하겠습니다. 두 토픽은 서로 상반되는 경향을 보입니다.
- 먼저 토픽 5의 경우
확산
에 초점을 맞추고 있습니다. 반면 토픽 6의 경우확진자
에 초점을 맞추고 있습니다. 또 토픽 5는정부
와중국
에 초점을 맞추고 있습니다. 반면 토픽 6의 경우 정부의 비중은 없으며중국
과중국인
의 비중이 매우 높게 나타납니다. 병명같은 경우 토픽 5는신종
,코로나바이러스
,감염증
등의 단어가 상대적으로 높게 나타나지만 토픽 6의 경우우한
,폐렴
의 비중이 월등히 높습니다.
- 위 내용을 바탕으로 두 토픽은 해당 기사의 성향을 나타낸다고 볼 수 있습니다. 진보성향 신문의 경우 신천지에 대한 기사를 바탕으로 병이 어떻게 확산되고 있는지에 대한 기사가 많았습니다. 반면 보수성향 신문의 경우 확진자 수를 강조하여 증가폭에 초점을 맞춘 기사가 많았습니다. 또 진보성향의 신문은 정부의 대응에 초점을 맞춘 반면 보수성향의 신문은 발원지인 중국과 중국인의 입국 금지에 대한 기사가 많았습니다. 병명의 경우 진보성향의 신문은 신종 코로나 바이러스, 코로나19등의 표현을 사용한 반면 보수성향의 신문은 우한폐렴이라는 다소 직설적인 표현을 사용하였습니다. 따라서 토픽 5와 6을 진보와 보수 성향의 신문이라고 판단해도 무리가 없을듯 합니다.
'데이터분석 저장소 > R 저장소' 카테고리의 다른 글
워드클라우드('19년도', '관광') (0) | 2020.05.15 |
---|---|
워드클라우드 (0) | 2020.05.07 |
데이터 핸들링 (0) | 2020.03.26 |
R 데이터 구조 및 기본 문법 (0) | 2020.03.22 |
R studio 다운로드 및 설정 (0) | 2020.03.21 |