Как получить правильные векторные эмбеддинги
Эта статья была первоначально опубликована в The New Stack и перепечатана здесь с разрешения.
Подробное введение в векторные эмбеддинги и способы их генерации с помощью популярных моделей с открытым исходным кодом.
Изображение Дениса Марчука с Pixabay
Векторные эмбеддинги крайне важны при работе с семантическим сходством. Однако вектор — это просто последовательность чисел; векторный эмбеддинг — это последовательность чисел, представляющая входные данные. Используя векторные эмбеддинги, мы можем структурировать неструктурированные данные или работать с любым типом данных, преобразуя его в последовательность чисел. Такой подход позволяет нам выполнять математические операции над входными данными, а не полагаться на качественные сравнения.
Векторные эмбеддинги важны для многих задач, особенно для семантического поиска. Однако перед их использованием крайне важно получить подходящие векторные эмбеддинги. Например, если вы используете модель для изображений, чтобы векторизовать текст, или наоборот, вы, вероятно, получите плохие результаты.
В этой статье мы узнаем, что означают векторные эмбеддинги, как генерировать правильные векторные эмбеддинги для ваших приложений с использованием различных моделей и как наиболее эффективно использовать векторные эмбеддинги с векторными базами данных, такими как Milvus и Zilliz Cloud.
Как создаются векторные эмбеддинги?
Теперь, когда мы понимаем важность векторных эмбеддингов, давайте узнаем, как они работают. Векторный эмбеддинг — это внутреннее представление входных данных в модели глубокого обучения, также известной как модель эмбеддингов или глубокая нейронная сеть. Итак, как извлечь эту информацию?
Мы получаем векторы, удаляя последний слой и беря выходные данные из предпоследнего слоя. Последний слой нейронной сети обычно выдает прогноз модели, поэтому мы берем выходные данные предпоследнего слоя. Векторный эмбеддинг — это данные, подаваемые на предсказательный слой нейронной сети.
Размерность векторного эмбеддинга эквивалентна размеру предпоследнего слоя в модели и, таким образом, взаимозаменяема с размером или длиной вектора. Распространенные размерности векторов включают 384 (генерируется Sentence Transformers Mini-LM), 768 (Sentence Transformers MPNet), 1 536 (OpenAI) и 2 048 (ResNet-50).
Что означает векторный эмбеддинг?
Однажды меня спросили о значении каждого измерения в векторном эмбеддинге. Короткий ответ — ничего. Отдельное измерение в векторном эмбеддинге ничего не означает, поскольку оно слишком абстрактно, чтобы определить его смысл. Однако, когда мы рассматриваем все измерения вместе, они передают семантическое значение входных данных.
Измерения вектора — это высокоуровневые абстрактные представления различных атрибутов. Представленные атрибуты зависят от обучающих данных и самой модели. Текстовые модели и модели изображений генерируют разные эмбеддинги, потому что они обучены на принципиально разных типах данных. Даже разные текстовые модели генерируют разные эмбеддинги. Иногда они различаются по размеру; в других случаях — по атрибутам, которые они представляют. Например, модель, обученная на юридических данных, усвоит не то же самое, что модель, обученная на данных здравоохранения. Я исследовал эту тему в своей статье сравнение векторных эмбеддингов.
Генерация правильных векторных эмбеддингов
Как получить правильные векторные эмбеддинги? Всё начинается с определения типа данных, которые вы хотите встроить. В этом разделе рассматривается встраивание пяти разных типов данных: изображений, текста, аудио, видео и мультимодальных данных. Все модели, которые мы здесь представляем, являются открытым исходным кодом и взяты из Hugging Face или PyTorch.
Эмбеддинги изображений
Распознавание изображений резко продвинулось в 2012 году после появления AlexNet. С тех пор область компьютерного зрения стала свидетелем многочисленных достижений. Последняя заметная модель распознавания изображений — ResNet-50, 50-слойная глубокая остаточная сеть, основанная на прежней архитектуре ResNet-34.
Остаточные нейронные сети (ResNet) решают проблему исчезающего градиента в глубоких сверточных нейронных сетях с помощью коротких соединений. Эти соединения позволяют выходу из более ранних слоев напрямую переходить к более поздним слоям, не проходя через все промежуточные слои, тем самым избегая проблемы исчезающего градиента. Такая архитектура делает ResNet менее сложной, чем VGGNet (Visual Geometry Group), ранее одна из лучших сверточных нейронных сетей.
В качестве примеров я рекомендую две реализации ResNet-50: ResNet 50 на Hugging Face и ResNet 50 на PyTorch Hub. Хотя сети одинаковы, процесс получения эмбеддингов отличается.
Пример кода ниже демонстрирует, как использовать PyTorch для получения векторных эмбеддингов. Сначала мы загружаем модель из PyTorch Hub. Затем удаляем последний слой и вызываем .eval() , чтобы указать модели вести себя так, как при выполнении инференса. Затем функция embed генерирует векторный эмбеддинг.
# Load the embedding model with the last layer removed
model = torch.hub.load('pytorch/vision:v0.10.0', 'resnet50', pretrained=True) model = torch.nn.Sequential(*(list(model.children())[:-1]))
model.eval()
def embed(data):
with torch.no_grad():
output = model(torch.stack(data[0])).squeeze()
return output
HuggingFace использует немного другую настройку. Код ниже демонстрирует, как получить векторный эмбеддинг из Hugging Face. Сначала нам нужны экстрактор признаков и модель из библиотеки transformers . Мы будем использовать экстрактор признаков, чтобы получить входные данные для модели, и использовать модель для получения выходных данных и извлечения последнего скрытого состояния.
# Load model directly
from transformers import AutoFeatureExtractor, AutoModelForImageClassification
extractor = AutoFeatureExtractor.from_pretrained("microsoft/resnet-50")
model = AutoModelForImageClassification.from_pretrained("microsoft/resnet-50")
from PIL import Image
image = Image.open("<image path>")
# image = Resize(size=(256, 256))(image)
inputs = extractor(images=image, return_tensors="pt")
# print(inputs)
outputs = model(**inputs)
vector_embeddings = outputs[1][-1].squeeze()
Текстовые эмбеддинги
Инженеры и исследователи экспериментируют с естественным языком и ИИ с момента изобретения ИИ. Некоторые из самых ранних экспериментов включают:
- ELIZA, первый чат-бот ИИ-терапевт.
- Китайскую комнату Джона Серла, мысленный эксперимент, который исследует, требует ли способность переводить между китайским и английским понимания языка.
- Переводы на основе правил между английским и русским.
Работа ИИ с естественным языком значительно эволюционировала от эмбеддингов на основе правил. Начав с базовых нейронных сетей, мы добавили рекуррентные связи через RNN, чтобы отслеживать шаги во времени. Затем мы использовали трансформеры для решения задачи преобразования последовательностей.
Трансформеры состоят из энкодера, который кодирует входные данные в матрицу, представляющую состояние, матрицы внимания и декодера. Декодер декодирует состояние и матрицу внимания, чтобы предсказать правильный следующий токен для завершения выходной последовательности. GPT-3, самая популярная на сегодняшний день языковая модель, состоит из строгих декодеров. Они кодируют входные данные и предсказывают правильный следующий токен(ы).
Вот две модели из библиотеки sentence-transformers от Hugging Face, которые можно использовать в дополнение к эмбеддингам OpenAI:
- MiniLM-L6-v2: 384-мерная модель
- MPNet-Base-V2: 768-мерная модель
Вы можете получать доступ к эмбеддингам обеих моделей одинаковым способом.
from sentence_transformers import SentenceTransformer
model = SentenceTransformer("<model-name>")
vector_embeddings = model.encode(“<input>”)
Мультимодальные эмбеддинги
Мультимодальные модели менее развиты, чем модели для изображений или текста. Они часто связывают изображения с текстом.
Самый полезный пример с открытым исходным кодом — CLIP VIT, модель преобразования изображений в текст. Вы можете получать доступ к эмбеддингам CLIP VIT так же, как и к модели изображений, как показано в коде ниже.
# Load model directly
from transformers import AutoProcessor, AutoModelForZeroShotImageClassification
processor = AutoProcessor.from_pretrained("openai/clip-vit-large-patch14")
model = AutoModelForZeroShotImageClassification.from_pretrained("openai/clip-vit-large-patch14")
from PIL import Image
image = Image.open("<image path>")
# image = Resize(size=(256, 256))(image)
inputs = extractor(images=image, return_tensors="pt")
# print(inputs)
outputs = model(**inputs)
vector_embeddings = outputs[1][-1].squeeze()
Аудиоэмбеддинги
ИИ для аудио получил меньше внимания, чем ИИ для текста или изображений. Самый распространенный сценарий использования аудио — преобразование речи в текст для таких отраслей, как колл-центры, медицинские технологии и доступность. Одна популярная модель с открытым исходным кодом для преобразования речи в текст — Whisper от OpenAI. Код ниже показывает, как получить векторные эмбеддинги из модели преобразования речи в текст.
import torch
from transformers import AutoFeatureExtractor, WhisperModel
from datasets import load_dataset
model = WhisperModel.from_pretrained("openai/whisper-base")
feature_extractor = AutoFeatureExtractor.from_pretrained("openai/whisper-base")
ds = load_dataset("hf-internal-testing/librispeech_asr_dummy", "clean", split="validation")
inputs = feature_extractor(ds[0]["audio"]["array"], return_tensors="pt")
input_features = inputs.input_features
decoder_input_ids = torch.tensor([[1, 1]]) * model.config.decoder_start_token_id
vector_embedding = model(input_features, decoder_input_ids=decoder_input_ids).last_hidden_state
Видеоэмбеддинги
Видеоэмбеддинги сложнее, чем аудио- или эмбеддинги изображений. При работе с видео необходим мультимодальный подход, поскольку они включают синхронизированные аудио и изображения. Одна популярная видеомодель — multimodal perceiver от DeepMind. Этот учебный notebook показывает, как использовать модель для классификации видео.
Чтобы получить эмбеддинги входных данных, используйте outputs[1][-1].squeeze() из кода, показанного в notebook, вместо удаления outputs. Я выделяю этот фрагмент кода в функции autoencode.
def autoencode_video(images, audio):
# создавать всё видео только один раз как входные данные
inputs = {'image': torch.from_numpy(np.moveaxis(images, -1, 2)).float().to(device),
'audio': torch.from_numpy(audio).to(device),
'label': torch.zeros((images.shape[0], 700)).to(device)}
nchunks = 128
reconstruction = {}
for chunk_idx in tqdm(range(nchunks)):
image_chunk_size = np.prod(images.shape[1:-1]) // nchunks
audio_chunk_size = audio.shape[1] // SAMPLES_PER_PATCH // nchunks
subsampling = {
'image': torch.arange(
image_chunk_size * chunk_idx, image_chunk_size * (chunk_idx + 1)),
'audio': torch.arange(
audio_chunk_size * chunk_idx, audio_chunk_size * (chunk_idx + 1)),
'label': None,
}
# прямой проход
with torch.no_grad():
outputs = model(inputs=inputs, subsampled_output_points=subsampling)
output = {k:v.cpu() for k,v in outputs.logits.items()}
reconstruction['label'] = output['label']
if 'image' not in reconstruction:
reconstruction['image'] = output['image']
reconstruction['audio'] = output['audio']
else:
reconstruction['image'] = torch.cat(
[reconstruction['image'], output['image']], dim=1)
reconstruction['audio'] = torch.cat(
[reconstruction['audio'], output['audio']], dim=1)
vector_embeddings = outputs[1][-1].squeeze()
# наконец, преобразуем модальности изображения и аудио обратно к исходной форме
reconstruction['image'] = torch.reshape(reconstruction['image'], images.shape)
reconstruction['audio'] = torch.reshape(reconstruction['audio'], audio.shape)
return reconstruction
return None
Хранение, индексирование и поиск векторных эмбеддингов с помощью векторных баз данных
Теперь, когда мы понимаем, что такое векторные эмбеддинги и как генерировать их с помощью различных мощных моделей эмбеддингов, следующий вопрос — как их хранить и использовать. Ответ — векторные базы данных.
Векторные базы данных, такие как Milvus и Zilliz Cloud , специально созданы для хранения, индексирования и поиска по огромным наборам неструктурированных данных с помощью векторных эмбеддингов. Они также являются одной из наиболее критически важных инфраструктур для различных AI-стеков.
Векторные базы данных обычно используют алгоритм приближенного ближайшего соседа (ANN) для вычисления пространственного расстояния между вектором запроса и векторами, хранящимися в базе данных. Чем ближе расположены два вектора, тем более релевантны они друг другу. Затем алгоритм находит k ближайших соседей и предоставляет их пользователю.
Векторные базы данных популярны в таких сценариях использования, как генерация с дополнением извлечением для LLM (RAG), системы вопросов и ответов, рекомендательные системы, семантический поиск, а также поиск сходства изображений, видео и аудио.
Чтобы узнать больше о векторных эмбеддингах, неструктурированных данных и векторных базах данных, начните с серии Vector Database 101 .
Резюме
Векторы — мощный инструмент для работы с неструктурированными данными. Используя векторы, мы можем математически сравнивать различные фрагменты неструктурированных данных на основе семантической близости. Выбор правильной модели векторных эмбеддингов критически важен для создания векторной поисковой системы для любого приложения.
В этом посте мы узнали, что векторные эмбеддинги являются внутренним представлением входных данных в нейронной сети. В результате они в значительной степени зависят от архитектуры сети и данных, использованных для обучения модели. Разные типы данных (такие как изображения, текст и аудио) требуют специальных моделей. К счастью, для использования доступно множество предварительно обученных моделей с открытым исходным кодом. В этом посте мы рассмотрели модели для пяти наиболее распространенных типов данных: изображений, текста, мультимодальных данных, аудио и видео. Кроме того, если вы хотите максимально эффективно использовать векторные эмбеддинги, векторные базы данных являются самым популярным инструментом.
Читать далее

Vector Lakebase: End the AI Data Silo
Learn how Vector Lakebase unifies vector search, data lakes, and AI data operations so teams can serve RAG and agents without copy-and-sync pipelines.

My Wife Wanted Dior. I Spent $600 on Claude Code to Vibe-Code a 2M-Line Database Instead.
Write tests, not code reviews. How a test-first workflow with 6 parallel Claude Code sessions turns a 2M-line C++ codebase into a daily shipping pipeline.

VidTok: Rethinking Video Processing with Compact Tokenization
VidTok tokenizes videos to reduce redundancy while preserving spatial and temporal details for efficient processing.



