Семантическое сходство — это то, что модели эмбеддингов призваны измерять, но на эти измерения влияет множество факторов смещения. В этой статье мы рассмотрим один распространенный источник смещения в моделях текстовых эмбеддингов: размер входных данных.
Эмбеддинги более длинных текстов обычно показывают более высокие показатели сходства при сравнении с другими текстовыми эмбеддингами, независимо от того, насколько похоже фактическое содержание. Хотя действительно похожие тексты по-прежнему будут иметь более высокие показатели сходства, чем несвязанные, длинные тексты вносят смещение — их эмбеддинги кажутся более похожими в среднем просто из-за их длины.
Это имеет реальные последствия. Это означает, что модели эмбеддингов сами по себе не способны хорошо измерять релевантность. При поиске на основе эмбеддингов всегда есть наилучшее совпадение, но смещение по размеру означает, что вы не можете использовать оценку сходства, чтобы определить, являются ли наилучшее совпадение или любые менее точные совпадения действительно релевантными. Вы не можете сказать, что, например, любое совпадение с косинусом выше 0.75 является релевантным, потому что длинный документ может легко соответствовать этому уровню, несмотря на полную нерелевантность.
Мы продемонстрируем это на простых примерах и покажем, почему косинусное сходство между текстовыми эмбеддингами не может служить универсальным способом оценки
tagВизуализация смещения по размеру
Чтобы показать, как проявляется смещение по размеру, мы будем использовать последнюю модель эмбеддингов Jina AI jina-embeddings-v3 с опцией text-matching
. Мы также будем использовать текстовые документы из широко используемого набора данных IR: набор данных CISI, который вы можете скачать с Kaggle.

Этот набор данных используется для обучения IR-систем, поэтому он содержит как запросы, так и документы для их сопоставления. Мы будем использовать только документы, которые все находятся в файле CISI.ALL
. Вы можете скачать его из командной строки из альтернативного источника на GitHub с помощью команды:
wget https://raw.githubusercontent.com/GianRomani/CISI-project-MLOps/refs/heads/main/CISI.ALL
CISI содержит 1 460 документов. Основная статистика о размерах текстов и их распределении по размерам приведена в таблице и гистограммах ниже:
в словах | в предложениях | |
---|---|---|
Средний размер документа | 119.2 | 4.34 |
Стандартное отклонение | 63.3 | 2.7 |
Максимальный размер | 550 | 38 |
Минимальный размер | 8 | 1 |


Давайте прочитаем документы в Python и получим для них эмбеддинги. Код ниже предполагает, что файл CISI.ALL
находится в локальной директории:
with open("CISI.ALL", "r", encoding="utf-8") as inp:
cisi_raw = inp.readlines()
docs = []
current_doc = ""
in_text = False
for line in cisi_raw:
if line.startswith("."):
in_text = False
if current_doc:
docs.append(current_doc.strip())
current_doc = ""
if line.startswith(".W"):
in_text = True
else:
if in_text:
current_doc += line
Это заполнит список docs
1 460 документами. Вы можете их просмотреть:
print(docs[0])
The present study is a history of the DEWEY Decimal
Classification. The first edition of the DDC was published
in 1876, the eighteenth edition in 1971, and future editions
will continue to appear as needed. In spite of the DDC's
long and healthy life, however, its full story has never
been told. There have been biographies of Dewey
that briefly describe his system, but this is the first
attempt to provide a detailed history of the work that
more than any other has spurred the growth of
librarianship in this country and abroad.
Теперь мы создадим эмбеддинги для каждого текста, используя jina-embeddings-v3. Для этого вам понадобится API-ключ с веб-сайта Jina AI. Вы можете получить бесплатный ключ на до 1 миллиона токенов эмбеддингов, чего достаточно для этой статьи.
Поместите ваш ключ в переменную:
api_key = "<Your Key>"
Теперь сгенерируйте эмбеддинги, используя задачу text-matching
с jina-embeddings-v3. Этот код обрабатывает тексты в docs
пакетами по 10.
import requests
import json
from numpy import array
embeddings = []
url = "https://api.jina.ai/v1/embeddings"
headers = {
"Content-Type": "application/json",
"Authorization": "Bearer " + api_key
}
i = 0
while i < len(docs):
print(f"Got {len(embeddings)}...")
data = {
"model": "jina-embeddings-v3",
"task": "text-matching",
"late_chunking": False,
"dimensions": 1024,
"embedding_type": "float",
"input": docs[i:i+10]
}
response = requests.post(url, headers=headers, data=json.dumps(data))
for emb in response.json()['data']:
embeddings.append(array(emb['embedding']))
i += 10
Для каждого текста в списке embeddings
будет эмбеддинг размерностью 1024. Вы можете увидеть, как это выглядит:
print(embeddings[0])
array([ 0.0352382 , -0.00594871, 0.03808545, ..., -0.01147173,
-0.01710563, 0.01109511], shape=(1024,))),
Теперь вычислим косинусы между всеми парами эмбеддингов. Сначала определим функцию косинуса cos_sim
, используя numpy
:
from numpy import dot
from numpy.linalg import norm
def cos_sim(a, b):
return float((a @ b.T) / (norm(a)*norm(b)))
Затем вычислим косинусы для каждого из 1 460 эмбеддингов по сравнению с остальными 1 459:
all_cosines = []
for i, emb1 in enumerate(embeddings):
for j, emb2 in enumerate(embeddings):
if i != j:
all_cosines.append(cos_sim(emb1, emb2))
Результатом является список из 2 130 140 значений. Их распределение должно приближаться к косинусам между "случайными" документами на одном языке и в одном регистре. Таблица и гистограмма ниже обобщают результаты.
Количество текстов | 1 460 |
---|---|
Количество косинусов | 2 130 140 |
Среднее | 0.343 |
Стандартное отклонение | 0.116 |

Эти документы, даже если они не связаны друг с другом, обычно имеют косинусы значительно выше нуля. Мы могли бы попытаться установить порог 0.459 (среднее + 1 стандартное отклонение) или, возможно, округлить его до 0.5, и сказать, что любая пара документов с косинусом меньше этого должна быть в значительной степени несвязанной.
Но давайте проведем тот же эксперимент на меньших текстах. Мы будем использовать библиотеку nltk
, чтобы разбить каждый документ на предложения:
import nltk
sentences = []
for doc in docs:
sentences.extend(nltk.sent_tokenize(doc))
Это дает 6 331 предложение со средней длиной 27.5 слов и стандартным отклонением 16.6. На гистограмме ниже распределение размеров предложений показано красным цветом, а для полных документов — синим, чтобы вы могли сравнить их.

Мы будем использовать ту же модель и методы для получения эмбеддингов для каждого предложения:
sentence_embeddings = []
i = 0
while i < len(sentences):
print(f"Got {len(sentence_embeddings)}...")
data = {
"model": "jina-embeddings-v3",
"task": "text-matching",
"late_chunking": False,
"dimensions": 1024,
"embedding_type": "float",
"input": sentences[i:i+10]
}
response = requests.post(url, headers=headers, data=json.dumps(data))
for emb in response.json()['data']:
sentence_embeddings.append(array(emb['embedding']))
i += 10
А затем вычислим косинус между эмбеддингами каждого предложения со всеми остальными:
sent_cosines = []
for i, emb1 in enumerate(sentence_embeddings):
for j, emb2 in enumerate(sentence_embeddings):
if i != j:
sent_cosines.append(cos_sim(emb1, emb2))
Результатом является значительно больше косинусных значений: 40 075 230, как показано в таблице ниже:
Number of sentences | 6,331 |
---|---|
Number of cosines | 40,075,230 |
Average | 0.254 |
Std. Deviation | 0.116 |
Косинусы между предложениями в среднем значительно ниже, чем между полными документами. На гистограмме ниже сравниваются их распределения, и вы можете легко увидеть, что пары предложений образуют почти идентичное распределение парам документов, но смещенное влево.

Чтобы проверить, что эта зависимость от размера устойчива, давайте получим все косинусы между предложениями и документами и добавим их к гистограмме. Их информация обобщена в таблице ниже:
Number of texts | 6,331 sentences & 1,460 documents |
---|---|
Number of cosines | 9,243,260 |
Average | 0.276 |
Std. Deviation | 0.119 |
Зеленая линия ниже — это распределение косинусов между предложениями и документами. Мы видим, что это распределение аккуратно располагается между косинусами документ-документ и предложение-предложение, показывая, что эффект размера затрагивает оба текста при сравнении — как больший, так и меньший.

Давайте проведем еще один тест, объединив документы группами по десять, создав 146 гораздо более крупных документов и измерив их косинусы. Результат обобщен ниже:
Number of texts | 146 documents |
---|---|
Number of cosines | 21,170 |
Average | 0.658 |
Std. Deviation | 0.09 |

Это намного правее других распределений. Порог косинуса 0.5 говорил бы нам, что почти все эти документы связаны друг с другом. Чтобы исключить нерелевантные документы такого размера, нам пришлось бы установить порог намного выше, возможно, до 0.9, что, несомненно, исключило бы хорошие совпадения среди меньших документов.
Это показывает, что мы не можем использовать минимальные пороги косинуса для оценки качества совпадения, по крайней мере без учета размера документа.
tagЧто Вызывает Смещение по Размеру?
Смещение по размеру в эмбеддингах не похоже на позиционные смещения в моделях с длинным контекстом. Оно не вызвано архитектурами. И дело не в самом размере. Например, если бы мы создавали более длинные документы, просто многократно concatenating копии одного и того же документа, это не показало бы смещения по размеру.
Проблема в том, что длинные тексты говорят больше вещей. Даже если они ограничены темой и целью, весь смысл написания большего количества слов состоит в том, чтобы сказать больше.
Более длинные тексты, по крайней мере те, которые люди обычно создают, естественным образом будут производить эмбеддинги, которые "распространяются" на большее семантическое пространство. Если текст говорит больше вещей, его эмбеддинг будет иметь меньший угол с другими векторами в среднем, независимо от темы текста.
tagИзмерение Релевантности
Урок этой статьи в том, что нельзя использовать косинусы между семантическими векторами сами по себе чтобы определить, является ли что-то хорошим совпадением, только то, что это лучшее совпадение из доступных. Нужно делать что-то помимо вычисления косинусов, чтобы проверить полезность и валидность лучших совпадений.
Можно попробовать нормализацию. Если вы можете эмпирически измерить смещение по размеру, возможно его компенсировать. Однако этот подход может быть не очень надежным. То, что работает для одного набора данных, вероятно, не будет работать для другого.
Асимметричное кодирование запросов и документов, предоставляемое в jina-embeddings-v3, уменьшает смещение по размеру в моделях эмбеддингов, но не устраняет его. Цель асимметричного кодирования состоит в том, чтобы кодировать документы менее "распространенно", а запросы — более.
Красная линия на гистограмме ниже — это распределение косинусов документ-документ с использованием асимметричного кодирования с jina-embeddings-v3 – каждый документ кодируется с использованием флагов retrieval.query
и retrieval.passage
, и каждый эмбеддинг запроса документа сравнивается с каждым эмбеддингом passage документа, который не из того же документа. Средний косинус равен 0.200 со стандартным отклонением 0.124.
Эти косинусы значительно меньше, чем те, которые мы нашли выше для тех же документов с использованием флага text-matching
, как показано на гистограмме ниже.

Однако асимметричное кодирование не устранило смещение по размеру. На гистограмме ниже сравниваются косинусы для полных документов и предложений с использованием асимметричного кодирования.

Среднее значение для косинусов предложений равно 0.124, поэтому при использовании асимметричного кодирования разница между средним косинусом предложений и средним косинусом документов составляет 0.076. Разница средних для симметричного кодирования составляет 0.089. Изменение смещения по размеру незначительно.
Хотя асимметричное кодирование улучшает эмбеддинги для информационного поиска, оно не лучше для измерения релевантности совпадений.
tagБудущие Возможности
Подход с использованием reranker, например jina-reranker-v2-base-multilingual и jina-reranker-m0, является альтернативным способом оценки совпадений запрос-документ, который, как мы уже знаем, улучшает точность запросов. Оценки reranker не нормализованы, поэтому они также не работают как объективные меры сходства. Однако они рассчитываются по-другому, и может быть возможно нормализовать оценки reranker таким образом, чтобы они стали хорошими оценщиками релевантности.
Другая альтернатива — использовать большие языковые модели, предпочтительно с сильными способностями к рассуждению, для прямой оценки того, является ли кандидат хорошим совпадением для запроса. Упрощенно говоря, мы могли бы спросить специализированную большую языковую модель: "По шкале от 1 до 10, является ли этот документ хорошим совпадением для этого запроса?" Существующие модели могут не подходить для этой задачи, но целенаправленное обучение и более сложные методы промптинга выглядят многообещающе.
Моделям не невозможно измерять релевантность, но это требует другой парадигмы, отличной от моделей эмбеддингов.
tagИспользуйте Ваши Модели для Того, в Чем Они Хороши
Эффект смещения по размеру, который мы задокументировали выше, показывает одно из фундаментальных ограничений моделей эмбеддингов: Они отлично сравнивают вещи, но ненадежны в измерении абсолютной релевантности. Это ограничение не является недостатком в дизайне — это неотъемлемая характеристика того, как работают эти модели.
Так что это значит для вас?
Во-первых, будьте скептичны к порогам косинуса. Они просто не работают. Меры косинусного сходства производят соблазнительно объективно выглядящие числа с плавающей точкой. Но то, что что-то выводит числа, не означает, что оно что-то объективно измеряет.
Во-вторых, рассмотрите гибридные решения. Эмбеддинги могут эффективно сузить большой набор элементов до перспективных кандидатов, после чего вы можете применить более сложные (и вычислительно интенсивные) методы, такие как rerankers или LLM, или даже человеческих оценщиков для определения реальной релевантности.
В-третьих, при проектировании систем думайте в терминах задач, а не возможностей. Объективно самая умная модель с наивысшими оценками в бенчмарках всё равно будет пустой тратой денег, если она не может выполнить работу, для которой вы её взяли.
Понимание ограничений наших моделей не является пессимистичным — это отражает более широкий принцип в приложениях: Понимание того, в чем ваши модели хороши, а в чем нет, критически важно для создания надежных и эффективных систем. Как мы не стали бы использовать молоток для закручивания винта, мы не должны использовать модели эмбеддингов для задач, с которыми они не могут справиться. Уважайте то, для чего ваши инструменты предназначены.