Intro
비교라는 것은 여러 대상에 대한 상대적인 차이를 논할 때 사용되는 단어이다. 자연어 처리에서 비교분석은 두개 이상의 Docs 중 어떤 Docs의 빈도가 더 높은지를 측정할 때 사용되곤 합니다. 특히나 logit 같은 경우에는 정말 빈도의 상대적인 차이 정도를 수치화 시켜놓았습니다. 반면 TF-IDF 단순히 Score의 개념을 넘어 Vector로 확장시켜 Semilarity를 계산하는 측도로도 사용되곤 합니다. 이번 칼럼을 통해서 logit과 TF-IDF에 대한 개념을 학습하게 보겠습니다.
LOR : log + Odds Ratio
LOR에 대해서 이해하기 위해서는 먼저 odds가 무엇인지에 대해서 이해해야 합니다.
odds란 발생한 횟수 / 발생하지 않은 횟수로 나눈 상대적인 값입니다. 확률이랑은 다르게 0부터 infinite 사이의 support를 가집니다. 이를 자연어 처리에서는 한 token이 해당 문서에서 발생한 횟수(빈도) / 발생하지 않은 나머지 token의 수로 구할 수 있습니다. 마찬가지로 해당 token이 해당 문서에서 얼마만큼의 중요도를 가지는지 확인해볼 수 있습니다 .
이런 odds들 간의 비율이 odds ratio입니다.
예를 들어 A라는 token이 C라는 doc에서 구한 odds와 D라는 doc에서 구한 odds 간의 비를 구하면 D라는 doc보다 C라는 doc에서 몇 배나 더 많이 출현한다는 사실을 얻을 수 있을 겁니다. 이런 방식으로 두 doc 에서 해당 token의 상대적 중요도를 측정할 수 있는 방법론입니다.
logit : log + odds 와는 다른 개념인가요?
logit은 말 그대로 odds에 log를 씌운 개념입니다. odds ratio에 log를 씌우면 이를 LOR이라고 합니다.
TF-IDF : Term Frequency + Inverse Document Frequency
TF-IDF는 단어의 빈도만을 고려하는 것이 아니라 전체 문서를 대상로 해당 Token의 출현 여부를 측정하는 IDF라는 값을 추가로 구해서 문서에 대한 상대적인 중요도를 정량화시킨 지표이다. Term Frequency는 Odds가 아닌 흔히 우리가 이해하고 있는 출현 확률이나 출현 빈도를 통해 구해주면 된다. (해당 token 출현 빈도 / 문서 내 전체 token의 수) 이때 확률을 쓰게 될 경우에는 각 문서를 정규화하는 효과가 있습니다. 다만 매번 정규화가 유용하냐..? 그건 아닙니다. 예를들어 doc 길이가 엄청 짧을 때는 확률이 오히려 왜곡된 결과를 가질 수 있습니다. 따라서 일반적으로는 TF로 출현 빈도를 사용합니다.
반면 IDF는 Document Frequency의 역수를 구한 값입니다. 이걸 왜 역수로 구하냐..? 라는 의문이 들 수 있습니다 .
저희가 DF를 역수로 구하게 되면 "총 문서의 수 / 특정 Token이 존재하는 문서 수" 가됩니다. 이때 문서가 존재안할 수도 있으니 분모에 1을 추가해줍니다. 그럼 "총 문서의수 / (특정 Token이 존재하는 문서 수 + 1)"이 됩니다. 여기서 우리가 해당 항에 log를 씌우게 된다면 이 inverse를 취한 항을 총문서의 수 - (특정 token이 존재하는 문서수 +1) 꼴로 두고 해석할 수 있습니다. 이 로그 선형식의 의미를 보면 많은 문서들에서 해당 token을 다루면 그만큼 값이 작아지는 효과가 있습니다. 즉 TF-IDF는 문서 내 단어의 빈도가 크고 여러 Doc보다 소수의 Doc에서 다루는 Token에 대해서 높은 Score를 주는 방법임을 알 수 있습니다 .
실제로 두 문장에 대하여 비교 분석 수행하기
비교분석을 위해서 불용어 전처리 후 동일한 Token을 가진 경우에 대해서만 결과를 표기했습니다.
from sklearn.feature_extraction.text import TfidfVectorizer
import numpy as np
import pandas as pd
# Define two sentences
sentence1 = "Machine learning is fascinating and rapidly growing."
sentence2 = "Deep learning is a subset of machine learning."
# Perform TF-IDF vectorization with stop words removal
tfidf = TfidfVectorizer(stop_words="english")
tfidf_matrix = tfidf.fit_transform([sentence1, sentence2])
tfidf_df = pd.DataFrame(tfidf_matrix.toarray(), columns=tfidf.get_feature_names_out())
# Extract TF-IDF scores for each sentence
tfidf_sentence1 = tfidf_df.iloc[0]
tfidf_sentence2 = tfidf_df.iloc[1]
# Filter for common tokens only
common_tokens = tfidf_sentence1.index[tfidf_sentence1 > 0].intersection(tfidf_sentence2.index[tfidf_sentence2 > 0])
# Calculate Log Odds Ratio for common tokens
epsilon = 1e-10
log_odds_ratio = np.log((tfidf_sentence1[common_tokens] + epsilon) / (tfidf_sentence2[common_tokens] + epsilon))
# Organize the results into a DataFrame
lor_df = pd.DataFrame({
'Token': common_tokens,
'TF-IDF Sentence1': tfidf_sentence1[common_tokens],
'TF-IDF Sentence2': tfidf_sentence2[common_tokens],
'Log Odds Ratio': log_odds_ratio
}).sort_values(by='Log Odds Ratio', ascending=False).reset_index(drop=True)
print(lor_df)
결과를 해석해보면 TF-IDF의 경우 Sentence 1과 2 중에서 machine에 대한 내용은 sentence 1에서 2% 정도 더 비중있게 다루고 있습니다. 반면 learning의 경우 sentence 1보다 sentence2에서 거의 2배 정도 더 비중있게 다루고 있습니다. 따라서 learning에 대한 내용이 강조되면서 mahcine에 대한 내용을 다루는 문장을 sentence 2이지 않을까 생각해볼 수 있겠습니다.
LOR을 비교해보면 machine의 경우 sentence 1쪽으로 0.06배 정도 더 비중있게 다룬 것을 볼 수 있습니다. 하지만 반대로 learning의 경우 sentence1보다 sentence2가 0.6배 더 비중있게 다룬 것을 볼 수 있습니다. machine에 대한 이야기는 둘다 비슷하게 다루지만 learning에 대한 언급이 sentence 2에서 높은 것을 보아서 sentence 2가 sentence1보다 learning에 대한 내용을 많이 다루고 있다고 해석해볼 수 있습니다.
이처럼 NLU 관점에서 비교분석해보는 실습까지 진행해보았습니다.
Outro
다음 칼럼에서는 NLP Retriver 모델에서 비교분석이 어떻게 쓰이는지에 대해서 알아보도록 하겠습니다.
인스타 주소 🎗
'MLOps > NLP' 카테고리의 다른 글
[NLU] 의미망 분석(Semantic Network Analysis)을 통한 관계 파악 (0) | 2024.11.10 |
---|---|
[NLU] Doc에 대한 감성 분석(Sentiment Analysis) (1) | 2024.11.10 |
[NLP] Retriver에서 사용되는 비교분석(Comparative Analysis) (0) | 2024.11.10 |
[NLU] 기본적인 명사 형태소 분석과 Tokenize의 필요성 (2) | 2024.11.09 |
NLP에 대한 기본 이해 (1) | 2024.11.09 |