스코어링
- 문서를 점수화 하는 방법
- TF: Term-Frequency
- 가장 간단한 스코어링 방법
- 검색하는 단어(term)가 포함된 빈도(frequency)
- 문제점:
- 단어 문서 행렬에서 한 문서는 단어 빈도를 통해 표현
- 단어 빈도가 비슷한 문서 = 의미가 비슷한 문서라는 가정
- 실제로는 정확하지가 않음 (예: 특정 단어가 무의미하게 반복되는 경우)
- 단어 빈도에 적절한 가중치를 주어 극복
단어 빈도의 가중치들
- 바이너리(binary): 단어의 빈도를 0 또는 1로만 표시 (1이상도 1)
- 로그 함수를 적용 log(1+count(t,d))
- 문서의 총 단어 빈도로 나눔
- 가장 많은 단어의 빈도로 나눔
문서 빈도 document frequency
- 문서빈도(df): 각 단어가 등장한(tf > 0) 문서의 수
- 역문서빈도(idf): 총 문서 수 n을 df로 나눈 값
- 로그 함수를 적용하여 차이를 줄임(10, 100, 1000… → 1, 2, 3…)
idf(t)=log1+df(t)1+n+1
- 여러 문서에 자주 나오면 df ↑, idf ↓
- 문서 간의 차이가 중요한 상황에서는 idf가 높은 단어가 좋은 단어
TF-IDF
- 단어 빈도(TF)와 역문서빈도(IDF)를 곱한 값
- 상대적으로 적은 문서에 나오면서 특정 문서에 자주 나온 단어
- 문서단어행렬에 가중치를 주는 대표적 방법
- 사이킷런에서는 CountVectorizer 대신 TfidfVectorizer를 사용하면 가중치가 적용된 문서단어행렬을 얻을 수 있음
TF-IDF (실습)
from sklearn.feature_extraction.text import TfidfVectorizer
tv = TfidfVectorizer(tokenizer=extract_nouns, min_df=10)
doc_vectors = tv.fit_transform(df.abstract)
doc_vectors[0].toarray()
from sklearn.feature_extraction.text import TfidfTransformer
tt = TfidfTransformer()
doc_vectors = tt.fit_transform(dtm)
doc_vectors[0].toarray()
유사한 단어 보기
word_vectors = doc_vectors.T
dist = pairwise_distances(word_vectors[j], word_vectors, metric='l2').flatten()
rank = np.argsort(dist)
[words[i] for i in rank[:10]]
TF-IDF의 확장
- Okapi BM25 ← 주로 검색에서 TF-IDF 대신 많이 쓰이는 방법
- TF-ICF
- ATC
- LTU
- MI
- PosMI
- Lin98
- Gref94
Okapi BM25
- f(qi,D): 문서 D에서 단어 qi의 빈도
- ∣D∣: 문서 길이 (avgdl: 평균 길이)
- k1: 단어 빈도의 포화(saturation)를 결정하는 하이퍼파라미터(보통 1.2 ~ 2.0)
- 단어 빈도가 k1을 넘어가면 점수가 잘 오르지 않음
- b: 문서 길이의 중요도를 반영하는 하이퍼파라미터(보통 0.75)
- 커질 수록 문서 길이를 많이 반영, 0이면 문서 길이는 미반영