for textmining

Topic Modeling, LDA

|

이번 글에서는 말뭉치로부터 토픽을 추출하는 토픽모델링(Topic Modeling) 기법 가운데 하나인 잠재디리클레할당(Latent Dirichlet Allocation, LDA)에 대해 살펴보도록 하겠습니다. 이번 글 역시 고려대 강필성 교수님 강의를 정리했음을 먼저 밝힙니다. 그럼 시작하겠습니다.

모델 개요

LDA란 주어진 문서에 대하여 각 문서에 어떤 주제들이 존재하는지에 대한 확률모형입니다. LDA는 토픽별 단어의 분포, 문서별 토픽의 분포를 모두 추정해 냅니다. LDA의 개략적인 도식은 다음과 같습니다.

우선 LDA는 특정 토픽에 특정 단어가 나타날 확률을 내어 줍니다. 예컨대 위 그림에서 노란색 토픽엔 gene이라는 단어가 등장할 확률이 0.04, dna는 0.02, genetic은 0.01입니다. 이 노란색 토픽은 대략 ‘유전자’ 관련 주제라는 걸 알 수 있네요.

이번엔 문서를 보겠습니다. 주어진 문서를 보면 파란색, 빨간색 토픽에 해당하는 단어보다는 노란색 토픽에 해당하는 단어들이 많네요. 따라서 위 문서의 메인 주제는 노란색 토픽(유전자 관련)일 가능성이 큽니다. 이렇듯 문서의 토픽 비중 또한 LDA의 산출 결과물입니다.

위 그림 우측에 있는 ‘Topic proportions & assignments’가 LDA의 핵심 프로세스입니다. LDA는 문서가 생성되는 과정을 확률모형으로 모델링한 것이기 때문인데요. 글쓰기를 예로 들면 이렇습니다.

우선 글감 내지 주제를 정해야 합니다. 이후 실제 글을 작성할 때는 어떤 단어를 써야할지 결정합니다. LDA도 마찬가지입니다. 우선 말뭉치로부터 얻은 토픽 분포로부터 토픽을 뽑습니다. 이후 해당 토픽에 해당하는 단어들을 뽑습니다. 이것이 LDA가 가정하는 문서 생성 과정입니다.

이제 반대 방향으로 생각해보겠습니다. 현재 문서에 등장한 단어들은 어떤 토픽에서 뽑힌 단어들일까요? 이건 명시적으로 알기는 어렵습니다. 말뭉치에 등장하는 단어들 각각에 꼬리표가 달려있는 건 아니니까요.

그런데 LDA는 이렇게 말뭉치 이면에 존재하는 정보를 추론해낼 수 있습니다. LDA에 잠재(Latent)라는 이름이 붙은 이유입니다. LDA의 학습은 바로 이러한 잠재정보를 알아내는 과정입니다.

모델 아키텍처

LDA의 아키텍처, 즉 LDA가 가정하는 문서생성과정은 다음과 같습니다. $D$는 말뭉치 전체 문서 개수, $K$는 전체 토픽 수(하이퍼 파라메터), $N$은 $d$번째 문서의 단어 수를 의미합니다. 네모칸은 해당 횟수만큼 반복하라는 의미이며 동그라미는 변수를 가리킵니다. 화살표가 시작되는 변수는 조건, 화살표가 향하는 변수는 결과에 해당하는 변수입니다.

우리가 관찰 가능한 변수는 $d$번째 문서에 등장한 $n$번째 단어 $w_{d,n}$이 유일합니다(음영 표시). 우리는 이 정보만을 가지고 하이퍼파라메터(사용자 지정) $α,β$를 제외한 모든 잠재 변수를 추정해야 합니다. 앞으로 이 글에서는 이 그림을 기준으로 설명할 예정이기 때문에 잘 기억해두시면 좋을 것 같습니다.

LDA의 문서생성과정은 다음과 같습니다. 이는 저도 정리 용도로 남겨두는 것이니 스킵하셔도 무방합니다.

(1) Draw each per-corpus topic distributions $ϕ_k$~$Dir(β)$ for $k∈${$1,2,…K$}

(2) For each document, Draw per-document topic proportions $θ_d$~$Dir(α)$

(3) For each document and each word, Draw per-word topic assignment $z_{d,n}$~$Multi(θ_d)$

(4) For each document and each word, Draw observed word $w_{d,n}$~$Multi(ϕ_{z_{d,n},n})$

LDA 모델의 변수

우선 각 변수를 설명하겠습니다. $ϕ_k$는 $k$번째 토픽에 해당하는 벡터입니다. 말뭉치 전체의 단어 개수만큼의 길이를 가졌습니다. 예컨대 $ϕ_1$은 아래 표에서 첫번째 열입니다. 마찬가지로 $ϕ_2$는 두번째, $ϕ_3$은 세번째 열벡터입니다. $ϕ_k$의 각 요소값은 해당 단어가 $k$번째 토픽에서 차지하는 비중을 나타냅니다. $ϕ_k$의 각 요소는 확률이므로 모든 요소의 합은 1이 됩니다(아래 표 기준으로는 열의 합이 1).

Terms Topic 1 Topic 2 Topic 3
Baseball 0.000 0.000 0.200
Basketball 0.000 0.000 0.267
Boxing 0.000 0.000 0.133
Money 0.231 0.313 0.400
Interest 0.000 0.312 0.000
Rate 0.000 0.312 0.000
Democrat 0.269 0.000 0.000
Republican 0.115 0.000 0.000
Cocus 0.192 0.000 0.000
President 0.192 0.063 0.000

그런데 아키텍처를 자세히 보면 $ϕ_k$는 하이퍼파라메터 $β$에 영향을 받는 걸 알 수 있습니다. 이는 LDA가 토픽의 단어비중 $ϕ_k$이 디리클레분포를 따른다는 가정을 취하기 때문입니다. LDA 기법에 디리클레라는 이름이 붙은 이유이기도 합니다. 디리클레분포 관련 자세한 내용은 이곳을 참고하시면 좋을 것 같습니다.

$θ_d$는 $d$번째 문서가 가진 토픽 비중을 나타내는 벡터입니다. 전체 토픽 개수 $K$만큼의 길이를 가집니다. 예컨대 $θ_1$은 아래 표에서 첫번째 행벡터, $θ_5$는 다섯번째 행벡터가 됩니다. $θ_d$의 각 요소값은 $k$번째 토픽이 해당 $d$번째 문서에서 차지하는 비중을 나타냅니다. $θ_d$는 확률이므로 모든 요소의 합은 1이 됩니다(아래 표 기준으로는 행의 합이 1).

Docs Topic 1 Topic 2 Topic 3
Doc 1 0.400 0.000 0.600
Doc 2 0.000 0.600 0.400
Doc 3 0.375 0.625 0.000
Doc 4 0.000 0.375 0.625
Doc 5 0.500 0.000 0.500
Doc 6 0.500 0.500 0.000

$θ_d$ 역시 하이퍼파라메터 $α$에 영향을 받습니다. 이는 LDA가 문서의 토픽비중 $θ_d$이 디리클레분포를 따른다는 가정을 취하기 때문입니다.

이번엔 $z_{d,n}$에 대해 살펴보겠습니다. $z_{d,n}$은 $d$번째 문서 $n$번째 단어가 어떤 토픽에 해당하는지 할당해주는 역할을 합니다. 예컨대 세번째 문서의 첫번째 단어는 ‘Topic2’일 가능성이 높겠네요. Topic1과 2가 뽑힐 확률이 각각 0.375, 0.625이거든요.

$w_{d,n}$은 문서에 등장하는 단어를 할당해주는 역할을 합니다. $ϕ_k$와 $z_{d,n}$에 동시에 영향을 받습니다. 의미는 이렇습니다. 직전 예시에서 $z_{3,1}$은 실제로 Topic2에 할당됐다고 칩시다. 이제 $ϕ_2$를 봅시다. 그러면 $w_{3,1}$은 Money가 될 가능성이 높겠네요. Topic2의 단어 분포 가운데 Money가 0.313으로 가장 높거든요.

LDA의 inference

지금까지 LDA가 가정하는 문서생성과정과 잠재변수들이 어떤 역할을 하는지 설명했습니다. 이제는 $w_{d,n}$를 가지고 잠재변수를 역으로 추정하는 inference 과정을 살펴보겠습니다. 다시 말해 LDA는 토픽의 단어분포와 문서의 토픽분포의 결합으로 문서 내 단어들이 생성된다고 가정합니다. LDA의 inference는 실제 관찰가능한 문서 내 단어를 가지고 우리가 알고 싶은 토픽의 단어분포, 문서의 토픽분포를 추정하는 과정입니다.

여기에서 LDA가 가정하는 문서생성과정이 합리적이라면 해당 확률과정이 우리가 갖고 있는 말뭉치를 제대로 설명할 수 있을 것입니다. 바꿔 말해 토픽의 단어분포와 문서의 토픽분포의 결합확률이 커지도록 해야 한다는 이야기입니다. 확률과정과 결합확률을 각각 그림과 수식으로 나타내면 다음과 같습니다. ($z_{d,n}$:per-word topic assignment, $θ_d$:per-document topic proportions, $ϕ_k$:per-corpus topic distributions)

\[\begin{align*} p(&{ \phi }_{ 1:K },{ \theta }_{ 1:D },{ z }_{ 1:D },{ w }_{ 1:D })=\\ &\prod _{ i=1 }^{ K }{ p({ \phi }_{ i }|\beta ) } \prod _{ d=1 }^{ D }{ p({ \theta }_{ d }|\alpha ) } \left\{ \prod _{ n=1 }^{ N }{ p({ z }_{ d,n }|{ \theta }_{ d })p(w_{ d,n }|{ \phi }_{ 1:K },{ z }_{ d,n }) } \right\} \end{align*}\]

위 수식에서 사용자가 지정한 하이퍼파라메터 $α,β$와 우리가 말뭉치로부터 관찰가능한 $w_{d,n}$을 제외한 모든 변수가 미지수가 됩니다. 따라서 우리는 사후확률(posterior) $p(z,ϕ,θ$|$w)$를 최대로 만드는 $z,ϕ,θ$를 찾아야 합니다. 이것이 LDA의 inference입니다. 그런데 사후확률을 계산하려면 분모에 해당하는 $p(w)$를 반드시 구해야 합니다. 이는 베이즈 정리에서 evidence로 불리는 것으로, $p(w)$는 잠재변수 $z,ϕ,θ$의 모든 경우의 수를 고려한 각 단어($w$)의 등장 확률을 가리킵니다. 그러나 $z,ϕ,θ$는 우리가 직접 관찰하는 게 불가능할 뿐더러, $p(w)$를 구할 때 $z,ϕ,θ$의 모든 경우를 감안해야 하기 때문에, 결과적으로 $p(w)$를 단번에 계산하는 것이 어렵습니다. 이 때문에 깁스 샘플링 같은 기법을 사용하게 됩니다. 깁스 샘플링 관련 자세한 내용은 이곳을 참고하시면 좋을 것 같습니다.

LDA와 깁스 샘플링

LDA에서는 나머지 변수는 고정시킨 채 한 변수만을 변화시키되, 불필요한 일부 변수를 샘플링에서 제외하는 collapsed gibbs sampling 기법을 씁니다. LDA에서는 $p(z,ϕ,θ$|$w)$를 구할 때 $ϕ,θ$를 계산에서 생략합니다. 깁스 샘플링으로 구한 $z$로 계산할 수가 있게 되거든요. 어쨌든 LDA의 깁스 샘플링 과정을 나타낸 수식은 다음과 같습니다.

\[p({ z }_{ i }=j|{ z }_{ -i },w)\]

위 식의 의미는 이렇습니다. 말뭉치가 주어졌기 때문에 $w$는 우리가 이미 알고 있는 값입니다. $z$는 각 단어가 어떤 토픽에 할당돼 있는지를 나타내는 변수인데요. $z_{-i}$는 $i$번째 단어의 토픽 정보를 제외한 모든 단어의 토픽 정보를 가리킵니다. 식 전체적으로는 $w$와 $z_{-i}$가 주어졌을 때 문서의 $i$번째 단어의 토픽이 $j$일 확률을 뜻합니다. 아래 그림을 볼까요?

위 그림에서 $z_i$는 record라는 단어가 속하는 토픽입니다. 깁스 샘플링을 위해 토픽 정보를 지워 놓았습니다. 나머지 단어에 대한 토픽 정보는 그대로 씁니다. 이것이 바로 $z_{-i}$입니다. 이 상태의 정보를 토대로 record라는 단어가 어떤 토픽에 속할지 할당하는 것이 LDA의 깁스 샘플링 과정입니다. 이해를 돕기 위해 그림 하나 더 보겠습니다.

위 그림은 이렇게 이해하면 됩니다. 각 행은 문서를 나타냅니다. 동그라미는 각 문서에 속한 단어들입니다. 동그라미 안의 숫자들은 토픽 ID입니다. 처음엔 랜덤하게 뿌려 놓습니다.

첫번째 깁스 샘플링 대상인 첫번째 문서의 첫번째 단어 $z_{0,0}$의 토픽 정보를 지웁니다. 나머지 단어들의 토픽정보를 토대로 가장 그럴싸한 토픽 ID를 새로 뽑았습니다. 예시 그림에선 3이네요.

이번엔 $z_{0,1}$ 차례입니다. 첫번째 문서의 두번째 단어 $z_{0,1}$의 토픽 정보를 지웁니다. 새로 뽑은 $z_{0,0}$을 포함한 나머지 단어들의 토픽정보를 토대로 가장 그럴싸한 토픽 ID를 또 새로 뽑습니다. 1입니다.

이런 식으로 문서 내 모든 단어와 말뭉치 내 모든 문서에 대해 깁스 샘플링을 반복하면 어느 순간부터는 모든 단어에 대한 토픽 할당 정보가 수렴하게 됩니다.

실제 계산과정

몇 가지 수식 정리 과정을 거치면 $d$번째 문서 $i$번째 단어의 토픽 $z_{d,i}$가 $j$번째에 할당될 확률은 다음과 같이 쓸 수 있습니다.

\[p({ z }_{d, i }=j|{ z }_{ -i },w)=\frac { { n }_{ d,k }+{ \alpha }_{ j } }{ \sum _{ i=1 }^{ K }{ ({ n }_{ d,i }+{ \alpha }_{ i }) } } \times \frac { { v }_{ k,{ w }_{ d,n } }+{ \beta }_{ { w }_{ d,n } } }{ \sum _{ j=1 }^{ V }{ ({ v }_{ k,j }+{ \beta }_{ j }) } }=AB\]

위 수식의 표기를 정리한 표는 다음과 같습니다.

표기 내용
$n_{d,k}$ $k$번째 토픽에 할당된 $d$번째 문서의 단어 빈도
$v_{k,w_{d,n}}$ 전체 말뭉치에서 $k$번째 토픽에 할당된 단어 $w_{d,n}$의 빈도
$w_{d,n}$ $d$번째 문서에 $n$번째로 등장한 단어
$α$ 문서의 토픽 분포 생성을 위한 디리클레 분포 파라메터
$β$ 토픽의 단어 분포 생성을 위한 디리클레 분포 파라메터
$K$ 사용자가 지정하는 토픽 수
$V$ 말뭉치에 등장하는 전체 단어 수
$A$ $d$번째 문서가 $k$번째 토픽과 맺고 있는 연관성 정도
$B$ $d$번째 문서의 $n$번째 단어($w_{d,n}$)가 $k$번째 토픽과 맺고 있는 연관성 정도

예를 들어보겠습니다. 우선 아래와 같이 단어 5개로 구성된 문서 doc1이 있고, 각 단어마다 토픽 $z_i$도 이미 할당돼 있다고 가정해 보겠습니다(초기엔 랜덤하게 할당을 하니 이렇게 가정하는 게 무리가 없습니다). 토픽 수는 사용자가 3개로 지정해 놓은 상태입니다.

Doc1의 $i$번째 단어의 토픽 $z_{1,i}$ 3 2 1 3 1
Doc1의 $n$번째 단어 $w_{1,n}$ Etruscan trade price temple market

말뭉치에 등장하는 모든 단어들을 대상으로 각각의 단어들이 어떤 토픽에 속해 있는지를 일일이 세어서 만든 표도 다음과 같다고 가정하겠습니다(이 표 역시 초기엔 랜덤 할당을 합니다)

구분 Topic1 Topic2 Topic3
Etruscan 1 0 35
market 50 0 1
price 42 1 0
temple 0 0 20
trade 10 8 1

이제 깁스 샘플링을 할 차례입니다. $p(z_{1,2})$를 구해 보겠습니다. $z_{1,-2}$, 즉 첫번째 문서의 두번째 단어의 토픽($z_2$) 정보를 지운 상태에서, 나머지 단어들의 토픽 할당 정보를 활용해 계산하게 됩니다.

$z_{1,i}$ 3 ? 1 3 1
$w_{d,n}$ Etruscan trade price temple market

위 표를 보면 $z_{1,2}$를 지우고 나니 첫번째 문서엔 1번/3번 토픽이 각각 절반씩 있는 걸 확인할 수 있습니다. 바꿔 말해 $n_{1,1}=2$, $n_{1,3}=2$라는 것이죠. $α$는 사용자가 지정하는 하이퍼파라메터로 깁스 샘플링 과정에서 변하는 값이 아니므로 $A$의 크기는 $n_{1,1}$과 $n_{1,3}$에 영향을 받을 겁니다. 즉, $z_{1,2}$가 2번 토픽이 될 확률은 0이고, 1번/3번은 같습니다. $A$는 아래 그림과 같이 이해할 수 있습니다.

이번엔 수식의 오른쪽 부분인 $B$를 보겠습니다. 전체 말뭉치를 대상으로 단어들의 토픽 할당 정보를 조사한 표는 다음과 같다고 칩시다. 여기서 주의할 점은 깁스 샘플링을 수행하면서 trade의 토픽 정보를 지웠으므로 단어별 토픽 분포 표에서 $v_{2,trade}$가 1이 줄어든다는 사실입니다.

구분 Topic1 Topic2 Topic3
Etruscan 1 0 35
market 50 0 1
price 42 1 0
temple 0 0 20
trade 10 8-1 1

어쨌든 위 표를 보면 우리의 관심인 trade라는 단어의 토픽은 Topic1일 가능성이 제일 높겠네요. 전체 말뭉치에서 trade의 토픽은 1번, 2번, 3번 순으로 많거든요. 바꿔 말해 $v_{1,trade}=10$, $v_{2,trade}=7$, $v_{3,trade}=1$입니다. $B$에 적용된 $β$ 역시 샘플링 과정에서 바뀌는 과정이 아니므로 $B$의 크기는 $v_k$에 가장 많은 영향을 받을 겁니다. 이를 그림으로 나타내면 다음과 같습니다.

$p(z_{1,2})$는 $A$와 $B$의 곱으로 도출됩니다. $A$와 $B$를 각각 직사각형의 높이와 너비로 둔다면, $p(z_{1,2})$는 아래와 같이 직사각형의 넓이로 이해할 수 있습니다.

이 계산 예시에서 $z_{1,2}$는 Topic1에 할당될 가능성이 제일 큽니다. 하지만 Topic3에 할당될 가능성도 Topic1에 비해선 작지만 아주 없는 건 아닙니다. 확률적인 방식으로 토픽을 할당하기 때문입니다.

어쨌든 결과적으로 $z_{1,2}$이 Topic1에 할당됐다고 가정해 보겠습니다. 그러면 Doc1의 토픽 분포($θ_1$)와 첫번째 토픽의 단어 분포($ϕ_1$)가 각각 다음과 같이 바뀝니다.

$z_{1,i}$ 3 1 1 3 1
$w_{d,n}$ Etruscan trade price temple market
구분 Topic1 Topic2 Topic3
Etruscan 1 0 35
market 50 0 1
price 42 1 0
temple 0 0 20
trade 10+1 7 1

이런 방식으로 모든 문서, 모든 단어에 대해 깁스 샘플링을 수행하면 모든 단어마다 토픽을 할당해줄 수가 있게 됩니다. 이 과정에서 $ϕ,θ$ 또한 자연스럽게 구할 수 있습니다. 보통 1000회~1만회 반복 수행하면 그 결과가 수렴한다고 합니다.

디리클레 파라메터의 역할

$d$번째 문서에 $i$번째로 등장하는 단어의 토픽이 $j$번째일 확률을 다시 쓰면 다음과 같습니다.

\[p({ z }_{d, i }=j|{ z }_{ -i },w)=\frac { { n }_{ d,k }+{ \alpha }_{ j } }{ \sum _{ i=1 }^{ K }{ ({ n }_{ d,i }+{ \alpha }_{ i }) } } \times \frac { { v }_{ k,{ w }_{ d,n } }+{ \beta }_{ { w }_{ d,n } } }{ \sum _{ i=1 }^{ V }{ { v }_{ k,j }+{ \beta }_{ j } } }=AB\]

$A$는 $d$번째 문서가 $j$번째 토픽과 맺고 있는 연관성 강도를 나타냅니다. $B$는 $d$번째 문서의 $n$번째 단어($w_{d,n}$)가 $j$번째 토픽과 맺고 있는 연관성의 강도를 가리킵니다.

그러면 여기에서 $α​$ 값은 어떤 역할을 할까요? 이전 예시에서 첫번째 문서에 Topic2에 할당된 단어들이 하나도 없었습니다($n_{1,2}=0​$). 원래대로라면 첫번째 문서가 Topic2와 맺고 있는 연관성 강도, 즉 $A​$는 0이어야 할 겁니다. 이렇게 되면 $z_{d,i}​$가 Topic2가 될 확률 또한 0이게 됩니다.

하지만 사용자가 지정하는 하이퍼파라메터 $α$ 존재 덕분에 $A$가 아예 0으로 되는 일을 막을 수 있게 됩니다. 일종의 smoothing 역할을 한다는 것이죠. 따라서 $α$가 클수록 토픽들의 분포가 비슷해지고, 작을 수록 특정 토픽이 크게 나타나게 됩니다. 이는 $β$가 $B$에서 차지하는 역할과 대동소이합니다.

아래는 디리클레 파라메터 변화에 따른 토픽 분포의 변화를 직관적으로 나타난 그림입니다.

최적 토픽 수 찾기

LDA의 토픽수 $K$는 사용자가 지정하는 하이퍼파라메터입니다. 최적 토픽수 또한 여러 실험을 통해 구해야 하는 미지수라는 이야기입니다. 최적 토픽수를 구하는 데 쓰는 Perplexity 지표가 있어 소개합니다.

LDA는 문서가 생성되는 과정을 확률모형으로 가정합니다. LDA로부터 추정된 토픽 정보($z$)를 활용해 계산한 각 단어의 발생확률이 클수록 학습 말뭉치가 생성되는 과정을 제대로 설명하는 것이라는 얘기입니다. 최적 토픽 수를 찾기 위한 방법도 이 아이디어를 차용합니다.

우선 깁스 샘플링으로 구한 $ϕ,θ$를 활용해 전체 문서, 모든 단어의 발생 확률 $p(w)$를 식으로 쓰면 다음과 같습니다. $p(w)$는 말뭉치에 등장한 모든 단어의 발생확률을 종합적으로 따지기 때문에 곱으로 연결되지만, 이를 로그를 취한 결과가 아래 식입니다.

\[\log { \left\{ p(w) \right\} } =\sum _{ d=1 }^{ D }{ \sum _{ j=1 }^{ V }{ { n }^{ jd }\log { \left[ \sum _{ k=1 }^{ K }{ { \theta }_{ k }^{ d }{ \phi }_{ k }^{ j } } \right] } } }\]

$log(p(w))$ 개념은 이렇습니다. 첫번째 문서 세번째 단어가 ‘King’이라고 칩시다. 이 단어가 첫번째 문서에 나타난 빈도가 3이라고 하면 $n^{31}=3$입니다. 여기에 토픽의 단어분포 정보인 $ϕ$와 문서의 토픽 비중 정보인 $θ​$를 element-wise 곱 방식으로 계산하게 됩니다. 그런데 ‘King’이라는 단어는 하나의 토픽에만 있는게 아니고 여러 토픽에 걸쳐 있을 수 있습니다. 흔한 단어일 경우 더욱 그렇겠지요. 그래서 모든 토픽에 대해 합을 계산하게 됩니다.

위 정보를 활용한 Perplexity 지표는 다음과 같이 구합니다.

\[Perplexity(w)=exp\left[ -\frac { log\left\{ p(w) \right\} }{ \sum _{ d=1 }^{ D }{ \sum _{ j=1 }^{ V }{ { n }^{ jd } } } } \right]\]

$p(w)$는 클수록 좋은 inference이므로 $exp(-log(p(w)))$는 작을수록 좋을 겁니다. 따라서 아래 그림처럼 토픽 수 $K$를 바꿔가면서 Perplexity를 구한 뒤 가장 작은 값을 내는 $K$를 최적의 토픽수로 삼으면 됩니다.



Comments