- 수업 내용 리마인드 및 아카이빙 목적의 업로드
LSA(Latent Semantic Analysis)는 문서의 단어 간 숨겨진 의미를 분석하는 강력한 방법 중 하나입니다. 이번 글에서는 LSA를 활용해 간단한 실습을 진행하고, 뉴스 데이터를 분석하는 과정을 단계별로 살펴보겠습니다.
1. LSA 간단 실습
LSA는 문서-단어 행렬(DTM)을 특이값 분해(SVD)를 통해 분석하는 방법입니다. 이를 통해 문서 내에 존재하는 잠재적 의미를 추출할 수 있어요.
1) DTM 행렬 생성
먼저, 예시 데이터로 문서-단어 행렬(DTM)을 만들어봅니다.
import numpy as np
A = np.array([[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]])
print('DTM의 크기(shape) :', np.shape(A))
이 행렬은 4개의 문서와 9개의 단어로 구성되어 있으며, 각 값은 단어가 문서에서 몇 번 등장했는지를 나타냅니다.
2) Full SVD
SVD를 통해 문서-단어 행렬을 분해합니다. SVD는 세 개의 행렬 U, S, VT로 분해되며, 이 행렬을 사용해 원본 행렬을 다시 근사할 수 있습니다.
U, s, VT = np.linalg.svd(A, full_matrices=True)
- U는 문서와 관련된 행렬이고, VT는 단어와 관련된 행렬입니다.
- S는 특이값 벡터로, 이를 대각 행렬로 변환해 다시 원본 행렬을 재구성할 수 있어요.
3) Truncated SVD
특이값 중 상위 2개만 보존해 차원을 축소한 SVD를 진행해봅니다. 이를 통해 차원을 축소하면서도 문서 간의 의미를 최대한 보존할 수 있죠.
S = S[:2,:2]
U = U[:,:2]
VT = VT[:2,:]
A_prime = np.dot(np.dot(U,S), VT)
이렇게 상위 특이값만을 사용해 근사한 행렬을 확인할 수 있습니다.
4) sklearn을 사용한 TruncatedSVD
더 간편하게 LSA를 구현하려면 Scikit-learn의 TruncatedSVD를 사용할 수 있습니다.
from sklearn.decomposition import TruncatedSVD
svd_model = TruncatedSVD(n_components=2, algorithm='randomized', random_state=42)
lsa_matrix = svd_model.fit_transform(A)
이 과정에서 문서-토픽 행렬과 단어-토픽 행렬을 얻을 수 있으며, 이를 통해 문서와 단어 간의 관계를 더 쉽게 분석할 수 있어요.
2. 뉴스 데이터를 활용한 LSA 분석
이번에는 실제 뉴스 데이터를 활용해 LSA를 적용해볼게요. Twenty Newsgroups 데이터는 사이킷런에서 제공하는 뉴스그룹 데이터로, 20개의 주제를 가진 뉴스 기사들로 구성되어 있습니다.
1) 데이터 로드 및 전처리
뉴스 데이터를 불러와 전처리를 진행합니다. 텍스트에서 특수 문자나 불필요한 단어들을 제거해 더 깔끔한 데이터를 만듭니다.
from sklearn.datasets import fetch_20newsgroups
import pandas as pd
dataset = fetch_20newsgroups(shuffle=True, random_state=1, remove=('headers', 'footers', 'quotes'))
documents = dataset.data
news_df = pd.DataFrame({'document':documents})
# 특수 문자 제거, 짧은 단어 제거, 소문자 변환
news_df['clean_doc'] = news_df['document'].str.replace("[^a-zA-Z]", " ", regex=True)
news_df['clean_doc'] = news_df['clean_doc'].apply(lambda x: ' '.join([w for w in x.split() if len(w)>3]))
news_df['clean_doc'] = news_df['clean_doc'].apply(lambda x: x.lower())
2) TF-IDF 벡터화
뉴스 기사를 TF-IDF로 벡터화합니다. 이 과정에서 상위 1,000개의 단어만을 보존하고, 너무 자주 등장하는 단어는 무시합니다.
from sklearn.feature_extraction.text import TfidfVectorizer
vectorizer = TfidfVectorizer(stop_words='english', max_features=1000, max_df=0.5, smooth_idf=True)
X = vectorizer.fit_transform(news_df['clean_doc'])
3) LSA를 통한 토픽 모델링
LSA를 적용해 20개의 토픽을 추출합니다. 각 토픽에 대해 상위 단어를 확인해봅니다.
svd_model = TruncatedSVD(n_components=20, algorithm='randomized', n_iter=100, random_state=10)
svd_model.fit(X)
terms = vectorizer.get_feature_names_out()
# 각 토픽에서 중요한 단어 출력
for idx, topic in enumerate(svd_model.components_):
sorted_indices = topic.argsort()[::-1][:5]
print("Topic %d:" % (idx+1), [(terms[i], topic[i].round(5)) for i in sorted_indices])
4) 문서별 토픽 확인
각 문서가 어떤 토픽에 가장 큰 기여를 하는지 확인할 수 있습니다.
lsa_matrix = svd_model.transform(X)
def get_document_topics(lsa_matrix, n=5):
for idx, doc in enumerate(lsa_matrix):
if idx == 10: break
print(f"Document {idx+1}:", [(f"Topic {i+1}", doc[i].round(5)) for i in doc.argsort()[::-1][:n]])
get_document_topics(lsa_matrix, n=5)
LSA(잠재 의미 분석)는 대규모 텍스트 데이터를 분석할 때 매우 유용한 기법입니다. 간단한 DTM 행렬을 통해 문서의 숨겨진 의미를 추출할 수 있고, 뉴스 데이터와 같은 실제 데이터를 분석할 때도 강력한 도구로 사용됩니다.
- LSA를 통해 문서-단어 간의 관계를 분석하고, 문서들이 어떤 주제에 속해 있는지 파악할 수 있습니다.
- TruncatedSVD를 활용하면 차원을 축소하면서도 중요한 정보를 보존해 문서 간 유사성을 분석할 수 있습니다.
'+ 개발' 카테고리의 다른 글
임베딩 기법 비교: Word2Vec, GloVe, FastText. (3) | 2024.09.15 |
---|---|
뉴스 데이터 LDA 분석(ft. Gensim & Scikit-learn) (11) | 2024.09.14 |
토픽 모델링(Topic Modeling)의 이해와 활용 (0) | 2024.09.12 |
리스트 컴프리헨션(List Comprehension) (0) | 2024.09.11 |
파이썬의 강력한 도구들(ft. Lambda, defaultdict, map) (0) | 2024.09.10 |