사전 역문서 빈도
알고리즘

역문서 빈도

gabury1고친 사람 github-actions[bot]

역문서 빈도는 낱말 하나가 문서 모음 안에서 얼마나 드문지를 숫자로 매겨 줍니다. 드문 낱말일수록 값이 큽니다. 거의 모든 문서에 든 낱말은 값이 0 에 가깝습니다. 검색 엔진은 이 값을 낱말의 무게로 삼아 흔한 낱말이 점수를 부풀리지 못하게 합니다.

쉽고 빠른 이해

역문서 빈도는 낱말마다 「얼마나 드문가」를 숫자로 달아 줍니다. 상품 설명 만 개 가운데 「상품」은 모든 글에 있어서 0 을 받습니다. 「노이즈캔슬링」은 열 개에만 있어서 3 을 받습니다.

이 숫자가 없으면 검색 엔진은 낱말이 맞은 횟수만 셉니다. 그러면 「상품」을 여러 번 쓴 엉뚱한 글이 위로 올라옵니다.

  1. 낱말마다 그 낱말이 든 문서가 몇 개인지 셉니다
  2. 전체 문서 수를 그 개수로 나눕니다. 드문 낱말일수록 큰 값이 나옵니다
  3. 나온 값에 로그를 씌워 차이를 눌러 줍니다

대가가 있습니다. 문서 모음이 바뀌면 값도 바뀝니다. 흔한 낱말로만 이루어진 검색어는 점수를 거의 못 얻습니다. 뜻이 같아도 글자가 다르면 다른 낱말로 셉니다.

상세

역문서 빈도는 낱말 하나를 받아 숫자 하나를 돌려줍니다. 그 숫자는 문서 모음 안에서 그 낱말이 얼마나 드문지를 나타냅니다. 줄여서 IDF(Inverse Document Frequency)라고 적습니다.

검색 엔진은 이 값을 낱말의 무게로 씁니다. 검색어가 「무선 노이즈캔슬링 이어폰」이면 세 낱말이 같은 몫을 하지 않습니다. 「노이즈캔슬링」이 맞은 문서가 「무선」만 맞은 문서보다 위로 가야 합니다. IDF 가 그 차이를 숫자로 줍니다.

운동장에서 친구 한 명을 찾는다고 해 봅시다. 「운동화를 신었어」라는 말은 거의 쓸모가 없습니다. 거기 있는 사람 대부분이 운동화를 신었기 때문입니다. 「빨간 모자를 썼어」라는 말 한마디면 바로 찾습니다.

IDF 는 이 감각을 낱말에 옮긴 값입니다. 많은 문서에 두루 든 낱말은 문서를 가려 주지 못합니다. 몇 문서에만 든 낱말은 그 몇 문서를 바로 짚어 줍니다.

문서 빈도

IDF 의 재료는 문서 빈도입니다. 문서 빈도는 그 낱말이 든 문서의 개수입니다. 줄여서 df(document frequency)라고 적습니다. 상품 설명 만 개 가운데 「이어폰」이 든 글이 백 개면 「이어폰」의 df 는 100 입니다.

df 는 한 문서 안에서 몇 번 나왔는지를 세지 않습니다. 들었는지만 봅니다. 어떤 글이 「이어폰」을 스무 번 써도 df 에는 1 만 보탭니다.

이렇게 세는 까닭은 IDF 가 「가려 주는 힘」을 재려는 값이기 때문입니다. 한 글에 스무 번 나와도 그 낱말로 가려낼 수 있는 글은 그 한 편입니다. 한 문서 안에서 몇 번 나왔는지는 낱말 빈도가 따로 맡습니다. 줄여서 TF(Term Frequency)라고 적습니다.

문서 빈도를 뒤집는 까닭

df 가 클수록 흔한 낱말입니다. 무게는 거꾸로 작아져야 합니다. 그래서 전체 문서 수를 df 로 나눕니다. 전체 문서 수는 N 으로 적습니다.

N 을 df 로 나눈 값은 「문서 몇 개에 하나꼴로 이 낱말이 드나」를 뜻합니다. 「이어폰」은 N 이 10000, df 가 100 이라 나눈 값이 100 입니다. 문서 백 개에 하나꼴로 든다는 뜻입니다. 이름의 「역」이 이 뒤집기를 가리킵니다.

로그로 차이를 누른다

나눈 값을 바로 무게로 쓰면 차이가 너무 벌어집니다. 문서 하나에만 든 낱말은 10000 입니다. 열 개에 든 낱말은 1000 입니다. 드문 낱말 하나가 점수를 혼자 다 차지하게 됩니다.

그래서 나눈 값에 로그를 씌웁니다. 밑이 10 인 로그는 값이 열 배 커질 때마다 결과를 1 씩만 올립니다. 10000 은 4 가 되고 1000 은 3 이 됩니다. 열 배 차이가 한 칸 차이로 줄어듭니다.

식으로 적으면 아래와 같습니다. N 은 전체 문서 수, df 는 문서 빈도입니다.

IDF = log(N / df)

아래 코드는 앞의 상품 설명 예를 이 식으로 셈합니다. 각 줄 오른쪽 주석이 돌려받는 값과 그 낱말입니다.

Python
import math

N = 10000  # 전체 상품 설명 수

def idf(df):
    return math.log10(N / df)

idf(10000)  # 0.0 · 상품
idf(1000)   # 1.0 · 무선
idf(100)    # 2.0 · 이어폰
idf(10)     # 3.0 · 노이즈캔슬링

「상품」은 모든 글에 들어 있어서 N 과 df 가 같습니다. 나눈 값은 1 입니다. 1 의 로그는 0 입니다. 이 낱말이 맞아도 점수에 보태는 것이 없습니다.

로그의 밑은 10 이 아니어도 됩니다. 자연로그를 쓰는 구현도 많습니다. 밑을 바꾸면 모든 낱말의 IDF 에 같은 수가 곱해질 뿐입니다. 낱말끼리의 크기 순서는 바뀌지 않습니다.

드문 낱말이 더 많이 알려 준다

이 식은 확률로도 읽을 수 있습니다. 문서 하나를 아무렇게나 골랐을 때 그 낱말이 들어 있을 확률은 df 를 N 으로 나눈 값입니다. IDF 는 이 확률의 역수에 로그를 씌운 값입니다.

확률이 작을수록 이 값은 커집니다. 드물게 일어나는 일일수록 그 일이 일어났다는 소식이 더 많은 것을 알려 줍니다. 정보 이론은 확률의 역수에 로그를 씌운 이 값을 정보량이라고 부릅니다. IDF 는 「이 낱말이 들어 있다」는 소식의 정보량으로 읽힙니다.

흔한 낱말이 저절로 가벼워진다

「그리고」·「이」·「하다」 같은 낱말은 거의 모든 문서에 있습니다. df 가 N 에 가까워서 IDF 가 0 에 가깝습니다. 목록을 따로 만들지 않아도 이런 낱말은 점수에 거의 보태지 못합니다.

검색에서 아예 빼 버리는 흔한 낱말을 불용어라고 부릅니다. 불용어 목록은 사람이 미리 정해 둔 낱말을 지웁니다. IDF 는 문서 모음을 보고 무게를 스스로 줄입니다.

그래서 한 모음에서만 흔한 낱말도 가벼워집니다. 법률 문서만 모은 곳에서는 「조항」이 거의 모든 글에 나옵니다. 「조항」은 불용어 목록에 없는 낱말입니다. 그래도 IDF 는 이 낱말을 가볍게 봅니다.

IDF 를 무게로 쓰는 셈식

IDF 는 혼자서는 문서의 순서를 못 정합니다. 「이어폰」의 IDF 는 어느 문서에서 보든 같은 값이기 때문입니다. 문서끼리 가르려면 문서마다 달라지는 값과 곱해야 합니다.

그 값이 낱말 빈도입니다. 낱말 빈도와 IDF 를 곱한 셈식이 TF-IDF(Term Frequency-Inverse Document Frequency)입니다. 이 문서에 자주 나오면서 다른 문서에는 드문 낱말이 점수를 많이 얻습니다.

TF-IDF 에서 낱말 빈도가 한없이 점수를 올리지 못하게 손본 셈식이 BM25(Best Matching 25)입니다. 두 셈식 모두 검색어 낱말마다 무게를 구해 더합니다. 그 합이 문서의 점수입니다. IDF 는 두 셈식에서 같은 몫을 합니다.

문서 모음이 값을 정한다

IDF 는 낱말만 보고는 안 나옵니다. 어느 문서 모음을 기준으로 셌는지가 값을 정합니다. 같은 「파이썬」도 뉴스 기사 모음에서는 드물어서 무게가 큽니다. 파이썬 강좌만 모은 곳에서는 모든 글에 있어서 0 입니다.

문서가 새로 들어오면 N 과 df 가 바뀝니다. 그러면 모든 낱말의 IDF 가 조금씩 움직입니다. 그래서 IDF 는 낱말 빈도와 미리 곱해 저장하기보다 검색할 때 그 시점의 N 과 df 로 셈하는 편이 흔합니다.

검색 엔진은 df 를 역색인에서 얻습니다. 역색인은 낱말마다 그 낱말이 든 문서 번호를 적어 둔 목록입니다. 한 낱말의 목록 길이가 곧 그 낱말의 df 입니다.

역색인을 만들 때 문서를 한 번 훑으면 모든 낱말의 df 를 셀 수 있습니다. 모음 전체의 낱말 수를 T 라 하면 드는 시간은 O(T) 입니다. 낱말 수가 두 배면 시간도 두 배라는 뜻입니다. 셈해 둔 df 가 있으면 IDF 하나는 나눗셈 한 번과 로그 한 번으로 나옵니다.

조각마다 따로 세면 점수가 어긋난다

문서가 많아지면 검색 엔진은 문서를 여러 조각에 나눠 담습니다. 이 조각을 샤드라고 부릅니다. 조각마다 자기 문서만 보고 N 과 df 를 세면 같은 낱말의 IDF 가 조각마다 달라집니다.

아래 그림은 문서 만 개를 두 조각에 반씩 나눈 모습입니다. 「이어폰」이 든 문서 백 개가 한쪽에 몰렸습니다.

flowchart TD
    subgraph A["조각 A · 문서 5000"]
        A1["이어폰 df 10 · IDF 2.7"]
    end
    subgraph B["조각 B · 문서 5000"]
        B1["이어폰 df 90 · IDF 1.7"]
    end
    A1 --> M["모두 모아 세면 · df 100 · IDF 2"]
    B1 --> M

내용이 같은 문서라도 조각 A 에 들면 「이어폰」 점수를 더 받습니다. 어느 조각에 들었느냐가 순위를 흔듭니다. 조각에 든 문서가 적을수록 이 흔들림이 커집니다.

모든 조각의 df 를 한데 모아 셈하면 값이 맞춰집니다. 대가는 검색할 때마다 조각끼리 df 를 한 번 더 주고받는 일입니다.

0 으로 나누는 문제와 셈식의 변형

df 가 0 인 낱말도 있습니다. 검색어에 든 낱말이 어느 문서에도 없을 때입니다. 그러면 N 을 0 으로 나누게 되어 값이 안 나옵니다.

그래서 식을 조금씩 손본 변형이 여럿 쓰입니다. 어디를 손봤는지에 따라 모으면 아래와 같습니다.

셈식 손본 곳
log(N / df) 가장 단순한 꼴
log(N / (df + 1)) df 가 0 이어도 나눗셈이 된다
1 + log(N / df) 모든 문서에 든 낱말도 무게 1 을 남긴다
log((N − df + 0.5) / (df + 0.5)) 확률로 유도한 꼴이다. BM25 가 이 꼴을 쓴다

1 + log(N / df) 꼴은 흔한 낱말도 낱말 빈도만큼은 점수에 보태게 합니다. 무게가 0 이면 곱한 결과도 0 이라 낱말 빈도가 아무 일도 못 하기 때문입니다.

BM25 가 쓰는 꼴은 df 가 N 의 절반을 넘으면 음수가 됩니다. 분자가 분모보다 작아지기 때문입니다. 문서 천 개 가운데 구백 개에 든 낱말은 밑이 10 인 로그로 약 −0.95 가 나옵니다.

음수가 되면 검색어 낱말이 맞아도 점수가 깎입니다. 그래서 로그 안에 1 을 더해 음수를 막는 구현이 많습니다.

변형이 여럿이라 같은 낱말도 시스템마다 IDF 가 다르게 나옵니다. 이 값은 한 시스템 안에서 낱말끼리 무게를 견주는 데 씁니다. 다른 시스템의 값과 견줄 숫자는 아닙니다.

IDF 가 못 보는 것

첫째는 뜻입니다. 「자동차」와 「차량」은 글자가 달라서 따로 셉니다. 「차량」이 드문 낱말이어도 「자동차」로 찾는 사람에게는 그 무게가 닿지 않습니다.

둘째는 흔한 낱말이 모여서 만드는 뜻입니다. 「to be or not to be」는 낱말 하나하나가 거의 모든 영어 문서에 있습니다. IDF 만 보면 이 검색어는 점수를 거의 못 얻습니다.

셋째는 작은 모음입니다. 문서가 스무 개뿐이면 한 문서에 든 낱말과 두 문서에 든 낱말의 차이가 우연일 수 있습니다. 그래도 IDF 는 그 차이를 무게 차이로 옮깁니다.

쓸 때와 안 쓸 때

낱말을 맞춰 찾는 검색 점수는 거의 다 IDF 를 품고 있습니다. 검색 엔진의 기본 점수를 쓰고 있다면 IDF 도 이미 쓰고 있습니다. 직접 셈할 일은 검색 엔진 밖에서 문서 모음을 다룰 때 주로 생깁니다. 글마다 핵심어를 뽑는 키워드 추출이 그런 예입니다.

문서 모음이 스무 개 수준으로 작거나 한 주제로 몰려 있으면 IDF 가 흔들립니다. 핵심 낱말까지 0 에 가까워지기도 합니다. 뜻이 맞는 글을 찾아야 할 때는 글의 뜻을 숫자 목록으로 옮기는 임베딩과 벡터 검색을 함께 씁니다.

관련 항목

역문서 빈도를 셈하는 재료와 자료구조

문서 빈도 · 낱말 빈도 · 역색인 · 포스팅 리스트 · 색인 · 샤드

역문서 빈도가 기대는 수학 개념

로그 함수 · 정보량 · 확률 · 지프의 법칙 · 스무딩

역문서 빈도를 무게로 쓰는 점수 셈식

TF-IDF · BM25 · BM25F · 벡터 공간 모델 · 확률 검색 모델 · 관련도 점수

역문서 빈도가 속하는 검색 기법

정보 검색 · 전문 검색 · 검색 엔진 · 랭킹 · 관련도 · 질의

역문서 빈도보다 앞서 낱말을 다듬는 처리 단계

불용어 · 분석기 · 토큰화 · 형태소 분석 · 어간 추출

역문서 빈도를 점수에 쓰는 검색 엔진

Apache Lucene · Elasticsearch · OpenSearch · Apache Solr

역문서 빈도가 못 잡는 뜻을 메우는 수단

임베딩 · 벡터 검색 · 동의어 사전 · 질의 확장

역문서 빈도로 푸는 텍스트 작업

키워드 추출 · 텍스트 분류 · 문서 군집화 · 스팸 필터

다른 이름: IDF · Inverse Document Frequency · 역 문서 빈도 · 역문헌 빈도