문서 길이
고친 사람 github-actions[bot]
문서 길이는 문서 하나에 든 낱말 수입니다. 검색 엔진은 이 값을 써서 길이가 다른 문서끼리 점수를 견줄 수 있게 맞춥니다. 긴 글이 그저 길다는 까닭만으로 위에 오지 않게 하려는 것입니다.
쉽고 빠른 이해
문서 길이는 글 하나에 든 낱말 수입니다. 「무선 이어폰 무선 충전 케이스」라는 상품 설명은 낱말 다섯 개라 길이가 5 입니다.
이 값이 없으면 검색 엔진은 검색어 낱말이 나온 횟수만 봅니다. 긴 글은 낱말이 많아서 검색어 낱말도 더 자주 나옵니다. 그러면 검색어를 더 다루지도 않은 긴 글이 위로 올라옵니다.
- 문서를 넣을 때 낱말을 세어 길이를 적어 둡니다
- 모든 문서의 길이로 평균을 구해 둡니다
- 검색할 때 이 문서가 평균보다 얼마나 긴지 보고 횟수 점수를 깎거나 올립니다
대가가 있습니다. 깎는 세기를 잘못 고르면 내용이 많아서 긴 글까지 아래로 밀립니다. 문서가 들어오고 나갈 때마다 평균도 바뀝니다.
상품명처럼 길이가 거의 고른 칸에서는 길이를 아예 안 보기도 합니다.
상세
한 장짜리 쪽지에 「캠핑」이 세 번 적혀 있으면 그 쪽지는 캠핑 이야기입니다. 삼백 쪽짜리 소설에 「캠핑」이 세 번 나오면 지나가는 장면 하나일 가능성이 큽니다. 같은 세 번이어도 글이 얼마나 긴지에 따라 무게가 다릅니다.
문서 길이는 이 감각을 숫자로 옮기는 재료입니다. 문서 하나에 든 낱말의 개수를 셉니다. 검색 공식에서는 흔히 dl(document length)로 줄여 적습니다.
무엇을 세나
문서 길이는 글자 수가 아니라 낱말 수입니다. 검색 엔진은 글을 받으면 먼저 낱말 단위로 자릅니다. 이렇게 자르는 일이 토큰화입니다. 잘린 조각 하나하나는 토큰입니다. 문서 길이는 이 토큰의 개수입니다.
아래 코드는 띄어쓰기로 자르는 가장 단순한 토큰화입니다. 오른쪽 주석이 그 줄이 내는 값입니다.
doc = "무선 이어폰 무선 충전 케이스"
tokens = doc.split()
len(tokens) # 5
len(set(tokens)) # 4
같은 낱말이 두 번 나오면 두 번 셉니다. 「무선」이 두 번이라 길이는 5 입니다. 서로 다른 낱말만 세면 4 가 나옵니다. 문서 길이로는 보통 앞의 값을 씁니다.
어떤 조각을 낱말로 칠지는 토큰화 규칙이 정합니다. 검색에서 빼 버리는 흔한 낱말이 불용어입니다. 「그리고」·「이」 같은 불용어를 빼고 세면 길이가 줄어듭니다.
한국어는 낱말 뒤에 조사가 붙습니다. 「이어폰을」을 한 덩어리로 세느냐 「이어폰」과 「을」로 나눠 세느냐에 따라 길이가 달라집니다. 뜻 단위로 나누는 처리가 형태소 분석입니다. 같은 규칙으로 자른 문서끼리만 문서 길이를 견줄 수 있습니다.
글자 수·파일 크기와 다르다
「문서 길이」라는 말은 검색 밖에서도 쓰입니다. 세는 단위가 저마다 달라서 같은 글이어도 값이 다르게 나옵니다.
| 뜻 | 세는 단위 | 주로 쓰는 곳 |
|---|---|---|
| 검색의 문서 길이 | 토큰화로 자른 낱말 | 검색 점수 보정 |
| 파일 크기 | 바이트 | 저장 공간 · 전송 |
| 글자 수 | 글자 | 화면 표시 · 입력 제한 |
| 언어 모델의 입력 길이 | 언어 모델이 자른 토큰 | 한 번에 넣을 수 있는 양 |
언어 모델도 토큰을 셉니다. 자르는 규칙은 검색과 다릅니다. 낱말 하나를 여러 조각으로 쪼개기도 합니다. 같은 글이어도 두 길이는 서로 맞지 않습니다.
긴 문서가 점수를 더 받는 까닭
문서 길이가 필요한 까닭은 낱말 빈도에 있습니다. 낱말 빈도는 검색어 낱말이 그 문서에 몇 번 나왔는지입니다. 줄여서 tf(term frequency)라고 적습니다. 검색 점수는 이 횟수가 많을수록 오릅니다.
긴 글은 두 가지 까닭으로 tf 가 커집니다. 첫째는 같은 말을 길게 늘어놓은 경우입니다. 이어폰 설명을 같은 내용으로 두 번 적으면 길이도 두 배, 「이어폰」의 tf 도 두 배가 됩니다. 다루는 내용은 늘지 않았습니다.
둘째는 다루는 내용이 많은 경우입니다. 이어폰과 충전기와 케이스를 한 글에서 모두 다루면 글이 길어집니다. 그만큼 여러 검색어에 걸립니다. 이런 글은 더 많은 질문에 답할 수 있습니다.
첫째 경우는 길이만큼 깎아야 점수가 내용을 따라갑니다. 둘째 경우는 너무 깎으면 쓸모 있는 글이 묻힙니다. 길이를 얼마나 세게 볼지 고르는 문제가 여기서 생깁니다.
TF-IDF(Term Frequency-Inverse Document Frequency)는 tf 에 낱말이 얼마나 드문지를 곱합니다. 여러 문서에 흔히 나오는 낱말에는 작은 값을 곱합니다. 몇 문서에만 나오는 드문 낱말에는 큰 값을 곱합니다. 이 곱하는 값은 낱말마다 정해질 뿐 문서 길이와는 상관이 없습니다.
곱한 뒤에도 긴 글의 tf 가 큰 것은 바뀌지 않습니다. 길이를 따로 보지 않으면 TF-IDF 도 같은 문제를 안고 갑니다.
평균 문서 길이와 견주기
문서 길이 하나만으로는 길다 짧다를 말할 수 없습니다. 낱말 200 개는 한 줄 댓글을 모은 곳에서는 아주 긴 글입니다. 논문을 모은 곳에서는 아주 짧은 글입니다.
그래서 문서 모음 전체의 평균과 견줍니다. 모든 문서의 길이를 더해 문서 수로 나눈 값이 평균 문서 길이입니다. 공식에서는 avgdl(average document length)로 적습니다. 문서 길이를 이 평균으로 나누면 「평균보다 몇 배 긴가」가 나옵니다.
아래 코드는 길이가 50·100·150 인 문서 셋으로 평균을 구합니다. 그다음 문서마다 그 배수를 셈합니다.
lengths = [50, 100, 150]
avgdl = sum(lengths) / len(lengths) # 100.0
50 / avgdl # 0.5
150 / avgdl # 1.5
나눈 값이 1 이면 평균 길이입니다. 1 보다 작으면 평균보다 짧습니다. 1 보다 크면 깁니다. 길이를 쓰는 검색 공식은 대개 이 배수를 재료로 받습니다.
필드마다 따로 잰다
문서 하나가 여러 칸으로 나뉘기도 합니다. 상품이면 상품명과 설명과 리뷰가 따로 있습니다. 검색 엔진에서는 이런 칸 하나하나가 필드입니다. 문서 길이도 필드마다 따로 잽니다.
상품명은 낱말 서너 개입니다. 설명은 수백 개입니다. 둘을 한데 견주면 상품명은 언제나 짧은 쪽이 됩니다. 평균 문서 길이도 필드마다 따로 구해서 상품명은 상품명끼리 견줍니다.
색인할 때 세어 두고 검색할 때 쓴다
색인은 검색 엔진이 미리 만들어 두는 찾아보기입니다. 검색할 때마다 문서를 처음부터 다시 훑지 않으려고 만듭니다. 문서 길이도 검색할 때마다 다시 세지 않습니다. 문서를 색인에 넣을 때 한 번 세어 문서 옆에 적어 둡니다.
평균 문서 길이는 길이의 합과 문서 수만 들고 있으면 바로 나옵니다. 문서가 들어오면 합에 그 길이를 더합니다. 문서 수에도 1 을 더합니다. 문서가 지워지면 반대로 뺍니다.
flowchart TD
subgraph 넣을때["문서를 넣을 때"]
T["토큰화"] --> L["문서 길이"]
L --> S["길이의 합 · 문서 수"]
end
subgraph 찾을때["검색할 때"]
S --> A["평균 문서 길이"]
L --> R["문서 길이 ÷ 평균 문서 길이"]
A --> R
end
위 묶음은 문서마다 한 번 일어나는 일입니다. 아래 묶음은 검색어가 들어올 때마다 일어납니다. 합과 문서 수가 바뀌므로 문서가 오갈 때마다 평균도 조금씩 움직입니다.
길이로 점수를 맞추는 세 방법
길이를 점수에 넣어 문서끼리 견줄 수 있게 맞추는 일이 길이 정규화입니다. 크기가 제각각인 값을 한 기준에 맞춘다는 뜻입니다. 방법은 크게 셋입니다. 아래에서 하나씩 보고 끝에서 표로 모읍니다.
첫째는 tf 를 문서 길이로 나누는 방법입니다. 가장 단순합니다. 낱말 다섯 개짜리 문서에 「이어폰」이 한 번 나오면 0.2 입니다. 낱말 천 개짜리 문서에 열 번 나와도 0.01 입니다. 낱말 몇 개짜리 짧은 글이 한 번만 걸려도 긴 글을 쉽게 앞지릅니다.
둘째는 벡터 공간 모델이 쓰는 방법입니다. 이 모델은 문서를 숫자 목록으로 봅니다. 낱말마다 그 낱말의 무게를 하나씩 적은 목록입니다. 무게로는 흔히 tf 나 TF-IDF 값을 씁니다. 이 목록이 벡터입니다.
벡터의 크기는 무게를 제곱해 모두 더한 값의 제곱근입니다. 낱말이 많이 든 문서일수록 이 값이 커집니다. 낱말 수와 같은 값은 아닙니다. 그래도 길이를 대신 재는 값 노릇을 합니다.
벡터를 제 크기로 나누면 크기가 1 이 됩니다. 그러면 문서끼리 남는 차이는 무게들이 어떤 비율로 섞였느냐뿐입니다. 이 비율을 벡터의 방향이라고 합니다.
검색어도 같은 방식으로 벡터로 만듭니다. 검색어와 문서의 방향이 얼마나 가까운지 잰 값이 코사인 유사도입니다. 크기를 1 로 맞췄으니 길이는 점수에 끼어들지 않습니다.
이 방법은 첫째 방법보다 긴 문서를 덜 깎습니다. 낱말이 고루 섞인 글이면 벡터 크기가 낱말 수보다 느리게 커지기 때문입니다. 그래도 짧은 문서가 관련 있는 정도보다 더 자주 위로 올라오는 경향이 남습니다. 앞에서 본 「다루는 내용이 많아서 긴 글」도 함께 깎이기 때문입니다.
셋째는 평균 길이를 기준점으로 삼습니다. 이 기준점을 피벗이라고 합니다. 방법의 이름 피벗 정규화가 여기서 왔습니다. 평균 길이인 문서는 손대지 않습니다. 평균보다 몇 배 긴지는 정해 둔 세기만큼만 반영합니다.
BM25(Best Matching 25)가 이 방법을 씁니다. BM25 는 검색에서 널리 쓰이는 점수 셈식입니다.
BM25 에서는 세기를 b 라는 값으로 정합니다. b 는 0 과 1 사이에서 고릅니다. 피벗 정규화가 이 세기를 반영해 문서마다 내는 값을 이 문서에서는 길이 보정이라고 부르겠습니다. 아래 코드는 앞의 평균 100 에서 b 를 0.75 로 두고 길이 보정을 셈합니다.
b = 0.75
def norm(dl):
return 1 - b + b * dl / avgdl
norm(50) # 0.625
norm(100) # 1.0
norm(150) # 1.375
평균 길이인 문서는 1 이라 손대지 않습니다. 150 짜리는 배수가 1.5 입니다. 길이 보정은 1.375 로 그보다 덜 커집니다.
식 1 - b + b * dl / avgdl 은 (1 - b) × 1 + b × 배수 와 같습니다. 1 은 길이를 무시하는 값입니다. 배수는 길이를 손대지 않고 반영하는 값입니다. 길이 보정은 이 둘을 b 비율로 섞은 값입니다.
b 가 0 이면 값이 언제나 1 이라 길이를 안 봅니다. b 가 1 이면 배수를 손대지 않고 씁니다. 그 사이의 b 는 배수를 얼마나 섞을지 정합니다.
BM25 는 길이 보정이 클수록 tf 에서 받는 점수를 줄입니다. 길이 보정이 1 보다 큰 긴 문서는 같은 tf 에서 점수를 덜 받습니다. 1 보다 작은 짧은 문서는 더 받습니다. 이렇게 낸 낱말마다의 점수를 더해 문서 점수를 냅니다.
세 방법을 나란히 놓으면 이렇습니다.
| 방법 | 하는 일 | 생기는 일 |
|---|---|---|
| 횟수를 길이로 나누기 | tf 를 문서 길이로 나눈다 | 아주 짧은 문서가 지나치게 높아진다 |
| 벡터 크기로 나누기 | 문서 벡터의 크기를 1 로 맞춘다 | 짧은 문서가 제 몫보다 자주 위에 온다 |
| 피벗 정규화 | 평균보다 몇 배 긴지를 b 만큼만 반영한다 | b 를 문서 모음에 맞춰 골라야 한다 |
길이를 덜 보거나 안 볼 때
길이 보정이 언제나 필요한 것은 아닙니다. 문서 길이가 거의 고르면 맞출 차이가 없습니다. 상품명이나 태그처럼 낱말 몇 개짜리 필드가 그렇습니다. 이런 필드에서는 길이 보정을 끄기도 합니다. BM25 에서는 b 를 0 으로 둡니다.
반대로 긴 문서가 대체로 더 쓸모 있는 모음도 있습니다. 길수록 다루는 내용이 많은 기술 문서 모음이 그런 예입니다. 이때 길이를 세게 깎으면 찾던 문서가 아래로 밀립니다. b 를 낮춰 덜 깎습니다.
어느 쪽인지는 문서 모음마다 다릅니다. 정답이 표시된 검색 결과가 있으면 b 를 바꿔 가며 시험해 고릅니다.
관련 항목
문서 길이를 재료로 쓰는 점수 셈식
BM25 · BM25F · TF-IDF · 벡터 공간 모델 · 확률 모델 · 관련도 점수
문서 길이로 점수를 맞추는 정규화 방법
길이 정규화 · 피벗 정규화 · 코사인 정규화 · 코사인 유사도 · 벡터 노름
문서 길이를 셀 때 거치는 처리 단계
토큰화 · 토큰 · 불용어 · 형태소 분석 · 분석기 · 어간 추출
문서 길이와 함께 쓰는 통계
낱말 빈도 · 문서 빈도 · 역문서 빈도 · 평균 문서 길이 · 포화
문서 길이가 적히는 색인 구조
문서 길이가 속하는 검색 기법
정보 검색 · 전문 검색 · 검색 엔진 · 랭킹 · 관련도
문서 길이를 점수에 쓰는 검색 엔진
Apache Lucene · Elasticsearch · OpenSearch · Apache Solr
다른 이름: Document Length