잠재 의미 분석(Latent Semantic Analysis)
Machine Learning/National Language Processing 2020. 12. 28. 08:20토픽 모델링(Topic Modeling) 이란 문서집합에서 추상적인 주제를 발견하기 위한 통계적 모델로, 잠재 의미 분석(Latent Semantic Analysis, LSA) / 잠재 디리클레 할당(Latent Dirichlet Allocation, LDA) 등의 알고리즘이 있다. LSA 는 기본적으로 DTM 이나 TF-IDF 행렬에 절단된 특이값 분해(truncated SVD) 를 사용하여 차원을 축소시키고, 단어들의 잠재적인 의미를 끌어내지만, SVD 의 특성상 새로운 데이터를 업데이트 하려면 처음부터 다시 계산해야 하는 단점이 있다.
특이값 분해(SVD) 는 A 가 m × n 행렬일 때,
3개의 행렬(U:m×m 직교행렬, VT:n×n 직교행렬, S:m×n 직사각 대각행렬) 의 곱으로 분해(decomposition) 하는 것이다.
(9 x 4) 행렬의 DTM 으로 절단된 특이값 분해(truncated SVD) 를 구하기.
import numpy as np # 아래와 같은 DTM 이 있다고 할 때, A = [ [0, 0, 0, 1, 0, 1, 1, 0, 0], [0, 0, 0, 1, 1, 0, 1, 0, 0], [0, 1, 1, 0, 2, 0, 0, 0, 0], [1, 0, 0, 0, 0, 0, 0, 1, 1] ] # (4 x 9) 행렬에서 # 일단 특이값 분해 full SVD 구하기 : U x s x VT # U : m×m 직교행렬, # s : m×n 직사각 대각행렬, # VT : n×n 직교행렬 이라 할 때, U, s, VT = np.linalg.svd(A, full_matrices=True) # 4 x 4 직교행렬 확인 print(U.round(2)) # [[ 0.24 0.75 0. 0.62] # [ 0.51 0.44 -0. -0.74] # [ 0.83 -0.49 -0. 0.27] # [ 0. -0. 1. -0. ]] # 특이값 s 를 대각행렬로 바꾸고 직교행렬 구하기 print(s.round(2)) # [2.69 2.05 1.73 0.77] S = np.zeros((4, 9)) S[:4, :4] = np.diag(s) # 특이값 s 를 대각행렬에 삽입 print(S.round(2)) # [[2.69 0. 0. 0. 0. 0. 0. 0. 0. ] # [0. 2.05 0. 0. 0. 0. 0. 0. 0. ] # [0. 0. 1.73 0. 0. 0. 0. 0. 0. ] # [0. 0. 0. 0.77 0. 0. 0. 0. 0. ]] # 9 x 9 직교행렬 확인 print(VT.round(2)) # [[ 0. 0.31 0.31 0.28 0.8 0.09 0.28 0. 0. ] # [ 0. -0.24 -0.24 0.58 -0.26 0.37 0.58 -0. -0. ] # [ 0.58 -0. 0. 0. -0. 0. -0. 0.58 0.58] # [-0. 0.35 0.35 -0.16 -0.25 0.8 -0.16 0. 0. ] # [-0. -0.78 -0.01 -0.2 0.4 0.4 -0.2 0. 0. ] # [-0.29 0.31 -0.78 -0.24 0.23 0.23 0.01 0.14 0.14] # [-0.29 -0.1 0.26 -0.59 -0.08 -0.08 0.66 0.14 0.14] # [-0.5 -0.06 0.15 0.24 -0.05 -0.05 -0.19 0.75 -0.25] # [-0.5 -0.06 0.15 0.24 -0.05 -0.05 -0.19 -0.25 0.75]] | cs |
여기까지 구해본 full SVD 를 역으로 계산해 보면 U x S x VT = A 와 같음을 알 수 있다.
이제 3개 행렬을 축소시킨 truncated SVD 를 구하여 다른 문서나 단어의 유사도를 구할 수 있다.
# Truncated SVD 구하기 # 특이값 상위 2개만 남기기 (t = 2) U = U[:, :2] S = S[:2, :2] VT = VT[:2, :] print(np.dot(np.dot(U,S), VT).round(2)) # [[ 0. -0.17 -0.17 1.08 0.12 0.62 1.08 -0. -0. ] # [ 0. 0.2 0.2 0.91 0.86 0.45 0.91 0. 0. ] # [ 0. 0.93 0.93 0.03 2.05 -0.17 0.03 0. 0. ] # [ 0. 0. 0. 0. 0. 0. 0. 0. 0. ]] | cs |
위와 같이 전체 코퍼스에서 절단된 특이값 분해를 구해야 하므로, 데이터를 추가하게 되면 전과정을 처음부터 다시 실행해야 하는 단점이 있다.
WRITTEN BY
- 손가락귀신
정신 못차리면, 벌 받는다.
,