Latent Dirichlet Allocation

6 minute read

문서의 주제

세상엔 수많은 글이 있다.
그리고 그 글에는 항상 주제가 있다.
영화에 관한 글, 음악에 관한 글, 소설이라면 카라마조프 일가에 대한 글 등
모든 문서에는 그 글이 직접적으로 언급하진 않지만 글에 내제된 주제가 반드시 존재한다.
예컨데 영화에 관련된 글이라고 해서 영화라는 단어만 나오는 것이 아니며
정확히 ‘영화’라는 단어 없이도 영화에 대한 주제를 다루는 글을 얼마든지 쓸 수 있다.
따라서 글의 주제란 직접 보고 추상적으로 생각하고 (abstract),
주변의 단어들을 고려해야 (context) 알 수 있는 것이다.
즉 주제는 앞에 바로 보이는 것이 아니라 글에 잠재되어 있다.

확률의 도입

세상엔 수많은 글이 있다.
그리고 그 글에는 수많은 단어가 있다.
그리고 그 단어에는 의미가 존재하고, 그 단어를 분류할 수 있다.
가령 배우라는 단어는 보통 영화, 드라마 등의 주제에 등장하고
금융, 은행이라는 단어는 보통 경제 쪽의 주제에 등장한다.
하지만 어디까지나 이것은 확률적으로만 존재한다.
은행, 금융이라는 단어가 좀 등장했다고 해서 그 글이 무조건 경제에 대한 글이라고 단정지을 수는 없다.

주제의 복합성

세상엔 수많은 글이 있다.
그리고 그 글에는 수많은 주제가 있다.
다시 말해 주제는 글들과 1:1관계를 맺고 있지 않다.
주제를 장르로, 글을 영화로 예를 들자면
기생충이라는 영화는 코미디, 공포, 스릴러, 가족 등의 다양한 주제를 한데 섞어놓았다.

이렇듯 한 글에서도 여러 주제를 다룰 수가 있다.
정확히는, 한 글에 여저가지 주제에 속하는 단어들을 쓸 수 있다.
가령 한 주식브로커의 사기와 그 흥망성쇠를 다룬 영화 ‘더 울프 오브 월스트리트’를 다룬 글에서는
경제 쪽에 속하는 단어들 한 뭉텅이와 영화에 관련된 단어, 또 미국의 당 시대를 다루는 단어들이 복합적으로 등장한다.
하지만 이 영화에 대해 전무한 사람도 레오나르도 디카프리오나 마틴 스콜세지 같은 사람 이름이 나오는 걸 보고
분명 무슨 영화에 대한 글이라고 생각은 할 수 있다.

글을 마구잡이로 쓰는 것이 아닌 이상은 주제는 하나이다.
그러므로 여러 주제에 속하는 단어를 쓰더라도 그 비율과
그 단어가 주제에 속할 확률(세기)가 존재한다.
여기서는 그래도 영화에 대한 글이니까 영화에 대한 단어가 많이 쓰였고
디카프리오, 스콜세지라는 단어는 영화란 주제에 속할 확률이 매우 높다.
사람은 이를 사전지식과 글들의 맥락에서 읽어내는 것이다.

하지만 컴퓨터도 그럴 수 있을까?

디리클레 분포

‘더 울프 오브 월스트리트’란 영화에 대한 글을 ‘울프’라고 하겠다.
이 ‘울프’에는 경제 관련 단어가 30%,
디카프리오, 스콜세지를 포함한 영화 관련 단어 50%,
미국 정치를 다룬 단어가 20% 등장한다고 하자.
그렇다면 이 문서는 각 주제에 해당할 확률이 (0.3, 0.5, 0.2) 라고 할 수 있다.
이렇게 ‘울프’는 각 주제의 확률에 관한 벡터로 표현할 수 있다.

특히 이렇게 k차원의 벡터가 모두 양수이며 합이 1이 되는 경우
이 확률의 분포를 디리클레 분포라고 한다.
이항분포고 정규분포고 하면서 중간(정규분포 때는 평균)에 곡선으로 우뚝 솟은 그래프를 그리듯이
k차원에서도 각 i(1<=i<=k)번째 값에 대한 값으로 그래프를 그릴 수 있다는 것이다.
이때 이 계산에는 ‘알파’라는 상수가 필요하다.
알파는 k개이며, 각각 알파1, 알파2 등등으로 불리며 각 i번째 확률에 매칭이 된다.

이 디리클레 분포로 k차원의 벡터가 (x1, x2, x3, … xk) 일 확률을 f(x1, x2, x3, … xk)이라고 하자.
i번째 알파에 대한 아주 복잡한 함수인 B를 B(α)라 할 때
f(x1, x2, x3, … xk) = 1/B(α) x Π(xi^(αi-1)) 이 된다.
이 식은 i번째 확률 xi를 αi 빼기 1만큼 제곱한 값을 모든 i (1<=i<=k) 에 대해 곱하고
이를 B(α)의 역수만큼 곱하는 것이다.
B 함수는 아주 복잡한 과정을 거친다.
어쨌든 상수 αi 를 넣어주는 것으로, 사용자가 αi를 몇으로 정하느냐에 따라서 그 그래프가 달라진다.

dirichlet

위 그래프는 k=3인 벡터에서 알파i의 쌍이 왼쪽부터 시계방향으로
(6, 2, 2), (3, 7, 5), (6, 2, 6), (2, 3, 4) 일 때의 3차원 그래프라고 한다.

실제의 예는 이보다 복잡하다.
지금의 예는 경제, 영화, 정치를 다룬 단어의 퍼센티지가 정해졌지만
두번째 단락에서도 말했듯 한 단어가 경제, 영화, 정치에 관한 단어일지는 확률적으로 정해진다고 하였다.
그리고 이 확률 역시 디리클레 분포를 따른다.

결론

위 네 개 단락에서 핵심적인 단어를 살펴보자.
첫번째 단락에서는 글의 주제는 앞에 있지 않고 글에 전반적으로 잠재되어 있다고 했다.
두번째 단락에서는 한 단어가 어떤 주제에 확률적으로 속한다고 하였다.
세번째 단락에서는 서로 다른 주제를 나타내는 단어들이 글에 복합적으로 존재한다고 하였고
네번째 단락에서는 그 복합적인 주제의 확률이 디리클레 분포를 따른다고 하였다.

따라서 글의 주제를 정하고 이를 범주화한다는 것은
글의 잠재된 주제에 관해서
디리클레 분포로 가장 그럴 듯한 확률을 가지는 주제를 찾아내
그 주제에 해당 글을 할당하는 것이라고 할 수 있다.

이를 잠재 디리클레 할당,
Latent Dirichlet Allocation, 줄여서 LDA라고 한다.

학습

LDA 모델은 인공 신경망은 아니지만
수많은 글들로 그 단어가 어떤 주제에 가장 그럴듯하게 속하는지를 점점 바꿔나간다는 점에서 학습이라고 할 수 있을 것 같다.
LDA는 두 가지 행렬을 필요로 한다.
단어-주제 행렬과 문서의 단어별 주제 행렬이다.
이를 각각 WT (word-topic) 행렬, DT(document-topic) 행렬이라 임의로 칭하겠다.

먼저 여러가지 책들이 있다. 이 책들은 강아지, 고양이, 치킨, 액션영화 등 다양한 주제의 책들이고
이들의 상위 주제로 동물, 음식, 영화 등이 있다고 할 수 있다.

그리고 위 셋 중 하나의 주제에 속하는 책 다섯 권만 보도록 하자.

1 : 기생충, 오스카까지
2 : 나쵸를 요리하는 법
3 : 마틴 스콜세지의 생애
4 : 강아지와 일주일 보내기
5 : 쿠엔틴 타란티노의 방에는

우리는 각 책이 어떤 주제에 속하는지 당연히 알 것이다.

그리고 그 책의 첫 다섯 단어를 뽑아보도록 하자.

단어/문서 1 2 3 4 5
기생충, 오스카까지 기생충 오스카 받았다 감독 작품
나쵸를 요리하는 법 나쵸 요리 오븐 먹는다 멕시코
마틴 스콜세지의 생애 뉴욕 위스키 갱스터 영화 데뷔
강아지와 일주일 보내기 강아지 발바닥 먹이 산책
쿠엔틴 타란티노의 방에는 비디오 극장 마신다 쉐이크 영화

여기서 맨 첫번째 책을 뽑아서 각 단어가 속할만한 주제를 랜덤으로 배치해본다.

단어/주제 동물 영화 영화 요리 동물
기생충, 오스카까지 기생충 오스카 받았다 감독 작품

이를 DT행렬이라고 한다.

그리고 WT 행렬은 각 주제별로 단어의 수를 구한 행렬이다.

단어/주제 동물 음식 영화
기생충 3 2 23
먹이 43 5 2
배우 3 6 34
강아지 42 10 5
필름 0 2 79

이는 WT 행렬로, 단어가 각 토픽이 될 확률 벡터이기도 하다.
행을 다 더한 다음 각각으로 나누어 주면 확률이 되기 때문이다.
예를 들어 먹이라는 단어는 총 50번 나왔으므로
동물이란 주제에 속할 확률은 43/50 = 0.86
음식일 확률은 0.1, 영화일 확률은 0.04이다.

<기생충, 오스카>까지라는 책의 DT행렬을 보자.
5개의 단어 중 동물이 두 개, 영화가 두 개, 요리가 하나이다.
따라서 이도 확률로 0.4, 0.4, 0.2 로 나타낼 수 있는 것이다.

우리는 이 두 행렬로 각 단어가 어떤 주제에 속하는 단어인지 예측할 것이다.
즉 DT 행렬에서 D에 해당하는 T를 바꿔가는 것이다.
그리고 그 예측이 끝나면 그 단어의 주제 수를 세어서 가장 높은 것이 그 책의 주제라고 할 수 있는 것이다.

d번째 문서에서 i번째 단어가 토픽 j에 해당할 확률을 P(Zdi = j) 라고 하자.
이때 그 단어 w가 주어지고, 문서에서 i번째가 아닌 다른 단어들을 뜻하는 Z-i가 주어진다.
이때 P(Zdi = j | Z-j, w) 를 수식으로 표현하면

image

식은 두 가지 부분으로 나뉜다.

왼쪽 분수의 분자에 있는 ndk는 d번째 문서에서 주제 k에 할당된 단어의 빈도이다.
DT 행렬에서 각각 2, 2, 1 등에 해당한다.

알파는 하이퍼파라미터로, 스무딩을 해주는 값이다.
n-grams 모델에서 단어의 확률이 0이 될 것을 고려해서 add-k 스무딩을 한다고 배웠는데, 그것과 비슷하다.
랜덤으로 하고 보니 만일 어떤 문서에 n번째 토픽에 할당된 단어가 없다면, 이 확률 값은 0이 될 것이다.
이러면 그 단어가 다른 문서에서 아무리 많이 나타났다 해도 (B가 커짐) 결과는 0이 된다.
알파는 이 사태를 방지하기 위한 값이다.

오른쪽의 v는 n번째 단어가 전체 문서에서 주제 k에 할당된 빈도이다.
WT 행렬에서 기생충으로 따지면 3, 2, 23 이 된다.

맨 오른쪽 항의 AB는 각각 의미하는 바가 있다.
A는 문서가 주제 k와 연관 맺는 정도, B는 그 문서의 단어가 주제 k와 연관 맺는 정도이다.

일단 책의 첫번째 단어 기생충의 T를 먼저 정해보자.
먼저 A 쪽을 정해보자.
기생충의 T를 가리고 보면 영화가 둘, 요리가 하나, 동물이 하나이다.
따라서 기생충은 영화에 관련된 단어일 확률이 높다고 본다.

이번엔 B 쪽을 정해보자.
이 시행에서 기생충의 T를 가렸으므로 기생충의 벡터는 2, 2, 23이 된다.
이렇게 되면 영화에서 23번 나왔으므로
결과적으로 영화 쪽에 할당해주게 된다.

단어/주제 영화 영화 영화 요리 동물
기생충, 오스카까지 기생충 오스카 받았다 감독 작품
단어/주제 동물 음식 영화
기생충 2 2 24
먹이 43 5 2
배우 3 6 34
강아지 42 10 5
필름 0 2 79

이렇게 DT, WT 행렬이 바뀌게 된다.

이런 과정을 반복하면 각 단어의 T가 수렴하게 되고
그 책에서 각 단어의 T의 분포를 계산하여
책이 어떤 주제의 책인지를 예측할 수 있다.

코드

코드는 LSA 때 했던 것을 재사용한다.
왜냐하면 사이킷런에는 LDA 를 계산해주는 함수가 있기 때문이다.

TruncatedSVD 부분을 LatentDirichletAllocation 으로 바꾸기만 하면 된다.

lda = LatentDirichletAllocation(n_components=20)
lda.fit_transform(cnnTF_IDF)
topics = lda.components_

하지만 결과는 대단했다!

image

확실히 저번 LSA 에서의 결과보다 단어가 어느정도 의미 있는 단어들로 뭉쳐있는 것을 확인할 수 있다.

1번은 아마 북한관련 뉴스일 것이다. (CNN에 북한 카테고리가 실제 있다.)
2번은 성소수자, 3번은 건강, 4번은 기술, 5번은 법정, 6번은 범죄, 7-8은 중동, 10번은 여행인가?
과학 뉴스, 음악, 영화 관련 뉴스도 새롭게 보인다.
여튼 저번에는 보이지 않는 주제가 또렷하게 보이는 것을 확인할 수 있다.