Подробный нетехнический анализ того, как искусственный интеллект использует цифровые отпечатки для организации мировой информации.
Делиться

Если вы работаете в сфере разработки искусственного интеллекта, изучаете или планируете работать с этой технологией, вы наверняка сталкивались с внедрением моделей на своем пути.
По своей сути, модель встраивания представляет собой нейронную сеть, обученную отображать похожие слова или предложения в непрерывное векторное пространство с целью математического приближения к тем объектам, которые контекстуально или концептуально схожи.
Проще говоря, представьте себе библиотеку, где книги рассортированы не только по автору и названию, но и по многим другим параметрам, таким как атмосфера, тема, настроение, стиль письма и т. д.
Ещё одна хорошая аналогия — сама карта. Представьте карту и два города, которые вы не знаете. Допустим, вы не очень хорошо разбираетесь в географии и не знаете, где на карте находятся Токио и Нью-Йорк. Если я скажу вам, что нам следует позавтракать в Нью-Йорке и пообедать в Токио, вы можете ответить: «Давайте сделаем это».
Однако, как только я дам вам координаты, чтобы вы могли проверить города на карте, вы увидите, что они находятся очень далеко друг от друга. Это как передать модели векторы данных: это и есть координаты!
Создание карты
Еще до того, как вы зададите вопрос, модель встраивания обучается. Она прочла миллионы предложений и выявила закономерности. Например, она видит, что слова «кот» и «котенок» часто встречаются в предложениях одного типа, в то время как слова «кот» и «холодильник» встречаются крайне редко.
Используя эти закономерности, модель присваивает каждому слову набор координат в математическом пространстве, подобно невидимой карте.
- Схожие понятия (например, «кошка» и «котенок») размещаются на карте рядом друг с другом.
- Понятия, которые в некоторой степени связаны между собой (например, «кошка» и «собака»), располагаются рядом, но не вплотную друг к другу.
- Совершенно не связанные между собой понятия (например, «кошка» и «квантовая физика») размещены в совершенно разных уголках карты, как Нью-Йорк и Токио.
Цифровой отпечаток
Отлично. Теперь мы знаем, как создавалась карта. Что будет дальше?
Теперь мы будем работать с этой обученной моделью эмбеддинга. Как только мы дадим модели предложение, например, «Пушистый котенок спит»:
- Оно не смотрит на буквы. Вместо этого оно посещает координаты на своей карте для каждого слова.
- Она вычисляет центральную точку (среднее значение) всех этих местоположений. Эта единственная центральная точка становится «отпечатком пальца» всего предложения.
- Это ставит метку на карте в том месте, где находится «отпечаток» вашего вопроса.
- Оглядывается по кругу, чтобы определить, какие еще отпечатки пальцев находятся поблизости.
Любые документы, которые «находятся» рядом с вашим вопросом на этой карте, считаются совпадением, поскольку они разделяют одну и ту же «атмосферу» или тему, даже если в них используются не совсем одинаковые слова .

Это как поиск книги не по конкретному ключевому слову, а по указанию на карте точки с надписью «все это книги о котятах», и предоставление модели возможности найти все книги в этом районе.
Этапы встраивания моделей
Давайте теперь рассмотрим, как шаг за шагом работает модель встраивания после получения запроса.
- Компьютер принимает текст.
- Разбивает фразу на отдельные элементы, то есть наиболее мелкие части, несущие смысл. Обычно это слово или его часть.
- Разбиение на блоки : входной текст разбивается на управляемые блоки (часто около 512 токенов), чтобы избежать перегрузки слишком большим объемом информации одновременно.
- Встраивание : оно преобразует каждый фрагмент текста в длинный список чисел (вектор), который действует как уникальный отпечаток пальца , представляющий смысл этого текста .
- Векторный поиск : Когда вы задаете вопрос, модель также преобразует ваш вопрос в «отпечаток пальца» и быстро вычисляет, какие из сохраненных фрагментов содержат наиболее математически схожие числа.
- Модель возвращает наиболее похожие векторы, которые связаны с фрагментами текста.
- Генерация : Если вы выполняете генерацию с расширенным поиском (Retrieval-Augmented Generation, RAG), модель передает эти несколько «удачных» фрагментов искусственному интеллекту (например, LLM), который их читает и выводит естественно звучащий ответ, основанный только на этой конкретной информации.
Программирование
Отлично. Мы много говорили. Теперь давайте попробуем немного поработать с кодом и применить эти концепции на практике.
Начнём с простого векторного представления BERT (Bidirectional Encoder Representations from Transformers). Оно было создано Google и использует архитектуру Transformer и её механизм внимания. Вектор для слова изменяется в зависимости от окружающих его слов.
# Imports from transformers import BertTokenizer # Load pre-trained BERT tokenizer tokenizer = BertTokenizer.from_pretrained("bert-base-uncased") # Sample text for tokenization text = "Embedding models are so cool!" # Step 1: Tokenize the text tokens = tokenizer(text, return_tensors="pt", padding=True, truncation=True) # View tokens {'input_ids': tensor([[ 101, 7861, 8270, 4667, 4275, 2024, 2061, 4658, 999, 102]]), 'token_type_ids': tensor([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]), 'attention_mask': tensor([[1, 1, 1, 1, 1, 1, 1, 1, 1, 1]])}Обратите внимание, как каждое слово было преобразовано в идентификатор. Поскольку у нас всего 5 слов, некоторые из них могли быть разбиты на два подслова.
- Идентификатор 101 связан с токеном [CLS]. Считается, что вектор этого токена отражает общее значение или информацию всего предложения или последовательности предложений. Это как штамп, указывающий LLM на значение этого фрагмента . [2]
- Идентификатор 102 связан с токеном [SEP] для разделения предложений. [2]
Далее применим модель встраивания к данным.
Встраивание
Вот ещё один простой фрагмент кода, где мы получаем текст и кодируем его с помощью универсальной модели встраивания all-MiniLM-L6-v2 .
from qdrant_client import QdrantClient, models from sentence_transformers import SentenceTransformer # 1. Load embedding model model = SentenceTransformer('all-MiniLM-L6-v2', device='cpu') # 2. Initialize Qdrant client client = QdrantClient(":memory:") # 3. Create embeddings docs = ["refund policy", "pricing details", "account cancellation"] vectors = model.encode(docs).tolist() # 4. Store Vectors: Create a collection (DB) client.create_collection( collection_name="my_collection", vectors_config = models.VectorParams(size=384, distance= models.Distance.COSINE) ) # Upload embedded docs (vectors) client.upload_collection(collection_name="my_collection", vectors= vectors, payload= [{"source": docs[i]} for i in range(len(docs))]) # 5. Search query_vector = model.encode("How do I cancel my subscription") # Result result = client.query_points(collection_name= 'my_collection', query= query_vector, limit=2, with_payload=True) print("nn ======= RESULTS =========") result.pointsРезультаты соответствуют ожиданиям. Это указывает на проблему с аннулированием аккаунта !
======= RESULTS ========= [ScoredPoint(id='b9f4aa86-4817-4f85-b26f-0149306f24eb', version=0, score=0.6616353073200185, payload={'source': 'account cancellation'}, vector=None, shard_key=None, order_value=None), ScoredPoint(id='190eaac1-b890-427b-bb4d-17d46eaffb25', version=0, score=0.2760082702501182, payload={'source': 'refund policy'}, vector=None, shard_key=None, order_value=None)]Что только что произошло?
- Мы импортировали предварительно обученную модель встраивания.
- Создана векторная база данных по нашему выбору: Qdrant [3].
- Встроил текст и загрузил его в базу данных векторных изображений в новую коллекцию.
- Мы отправили запрос.
- В результате отображаются документы, наиболее близкие по математическому «отпечатку пальца», или смыслу, к векторным представлениям запроса.
Это действительно здорово.
В заключение этой статьи я хотел бы предложить вам попробовать доработать модель встраивания. Давайте попробуем.
Тонкая настройка модели встраивания
Тонкая настройка модели встраивания отличается от тонкой настройки модели LLM. Вместо того чтобы учить модель «говорить», вы учите ее реорганизовывать свою внутреннюю карту таким образом, чтобы определенные понятия в вашей предметной области отодвигались дальше друг от друга или сближались.
Наиболее распространенный и эффективный способ сделать это — использовать контрастивное обучение с помощью такой библиотеки, как Sentence-Transformers.
Сначала научите модель, что такое близость, используя три точки данных.
- Якорь : Ссылочный элемент (например, «Бренд газировки А»).
- Положительный момент : Похожий товар (например, «Кола марки B»), который модель должна подобрать.
- Отрицательный момент : Другой товар (например, «Кола без сахара марки А»), который модель должна оттолкнуть.
Далее мы выбираем функцию потерь, чтобы указать модели, насколько её следует изменить при совершении ошибки. Вы можете выбрать одну из следующих функций:
- MultipleNegativesRankingLoss : Отлично подходит, если у вас есть только пары (Якорь, Положительный результат). Предполагается, что каждый второй положительный результат в пакете является «отрицательным» для текущего якоря.
- TripletLoss : Лучше всего использовать, если у вас есть явно заданные наборы (якорь, положительный элемент, отрицательный элемент). Он заставляет расстояние между якорем и положительным элементом быть меньше, чем расстояние между якорем и отрицательным элементом на определенную величину.
Это результаты сравнения моделей, полученные без дополнительных настроек.
from sentence_transformers import SentenceTransformer, InputExample, losses from torch.utils.data import DataLoader from sentence_transformers import util # 1. Load a pre-trained base model model = SentenceTransformer('all-MiniLM-L6-v2') # 1. Define your test cases query = "Brand A Cola Soda" choices = [ "Brand B Cola Soda", # The 'Positive' (Should be closer now) "Brand A Cola Soda Zero Sugar" # The 'Negative' (Should be further away now) ] # 2. Encode the text into vectors query_vec = model.encode(query) choice_vecs = model.encode(choices) # 3. Compute Cosine Similarity # util.cos_sim returns a matrix, so we convert to a list for readability cos_scores = util.cos_sim(query_vec, choice_vecs)[0].tolist() print(f"nn ======= Results for: {query} ===============") for i, score in enumerate(cos_scores): print(f"-> {choices[i]}: {score:.5f}") ======= Results for: Brand A Cola Soda =============== -> Brand B Cola Soda: 0.86003 -> Brand A Cola Soda Zero Sugar: 0.81907А когда мы пытаемся уточнить модель, показав ей, что кола должна быть ближе по вкусу, чем версия без сахара, происходит вот что.
from sentence_transformers import SentenceTransformer, InputExample, losses from torch.utils.data import DataLoader from sentence_transformers import util # 1. Load a pre-trained base model fine_tuned_model = SentenceTransformer('all-MiniLM-L6-v2') # 2. Define your training data (Anchors, Positives, and Negatives) train_examples = [ InputExample(texts=["Brand A Cola Soda", "Cola Soda", "Brand C Cola Zero Sugar"]), InputExample(texts=["Brand A Cola Soda", "Cola Soda", "Brand A Cola Zero Sugar"]), InputExample(texts=["Brand A Cola Soda", "Cola Soda", "Brand B Cola Zero Sugar"]) ] # 3. Create a DataLoader and choose a Loss Function train_dataloader = DataLoader(train_examples, shuffle=True, batch_size=16) train_loss = losses.TripletLoss(model=fine_tuned_model) # 4. Tune the model fine_tuned_model.fit(train_objectives=[(train_dataloader, train_loss)], optimizer_params={'lr': 9e-5}, epochs=40) # 1. Define your test cases query = "Brand A Cola Soda" choices = [ "Brand B Cola Soda", # The 'Positive' (Should be closer now) "Brand A Cola Zero Sugar" # The 'Negative' (Should be further away now) ] # 2. Encode the text into vectors query_vec = fine_tuned_model.encode(query) choice_vecs = fine_tuned_model.encode(choices) # 3. Compute Cosine Similarity # util.cos_sim returns a matrix, so we convert to a list for readability cos_scores = util.cos_sim(query_vec, choice_vecs)[0].tolist() print(f"nn ======== Results for: {query} ====================") for i, score in enumerate(cos_scores): print(f"-> {choices[i]}: {score:.5f}") ======== Results for: Brand A Cola Soda ==================== -> Brand B Cola Soda: 0.86247 -> Brand A Cola Zero Sugar: 0.75732Здесь мы не получили значительно лучшего результата. Эта модель обучалась на очень большом объеме данных, поэтому тонкой настройки на небольшом примере оказалось недостаточно, чтобы она работала так, как мы ожидали.
Но всё же это отличный урок. Нам удалось приблизить модель к обоим примерам с колой, но это также приблизило нас к модели с колой без газа.
Выравнивание и однородность
Хороший способ проверить, как была обновлена модель, — это проанализировать следующие показатели.
- Выравнивание : Представьте, что у вас есть набор связанных элементов, например, «Бренд газировки A» и «Газировка Cola». Выравнивание измеряет, насколько близко эти связанные элементы находятся друг к другу в пространстве векторных представлений.
- Высокий показатель выравнивания означает, что ваша модель хорошо справляется с размещением похожих элементов близко друг к другу, что, как правило, необходимо для таких задач, как поиск похожих товаров.
- Равномерность : Теперь представьте все ваши различные элементы, от «политики возврата» до «квантовых вычислений». Равномерность измеряет, насколько равномерно распределены все эти элементы в пространстве вложений. Вам нужно, чтобы они были равномерно распределены, а не сгруппированы в одном углу.
- Хорошая однородность означает, что ваша модель может эффективно различать различные понятия и избегать сопоставления всего с небольшой, плотно расположенной областью.
Хорошая модель встраивания должна быть сбалансированной. Она должна сближать похожие элементы (хорошее выравнивание), одновременно отдаляя несхожие элементы и обеспечивая эффективное использование всего пространства (хорошая однородность). Это позволяет модели улавливать значимые взаимосвязи, не жертвуя при этом способностью различать различные понятия.
В конечном итоге, идеальный баланс часто зависит от конкретного приложения. Для некоторых задач, таких как семантический поиск, вы можете отдавать приоритет очень строгому выравниванию, в то время как для других, таких как обнаружение аномалий, более высокая степень однородности может быть более критичной.
Это код для вычисления выравнивания, которое представляет собой среднее значение косинусного сходства между опорными точками и положительными совпадениями.
from sentence_transformers import SentenceTransformer, util import numpy as np import torch # --- Alignment Metric for Base Model --- base_alignment_scores = [] # Assuming 'train_examples' was defined in a previous cell and contains (anchor, positive, negative) triplets for example in train_examples: # Encode the anchor and positive texts using the base model anchor_embedding_base = model.encode(example.texts[0], convert_to_tensor=True) positive_embedding_base = model.encode(example.texts[1], convert_to_tensor=True) # Calculate cosine similarity between anchor and positive score_base = util.cos_sim(anchor_embedding_base, positive_embedding_base).item() base_alignment_scores.append(score_base) average_base_alignment = np.mean(base_alignment_scores)А вот код для расчета равномерности. Он выполняется следующим образом: сначала берется разнообразный набор эмбеддингов, затем вычисляется косинусное сходство между каждой возможной парой этих эмбеддингов, и, наконец, усредняются все эти попарные оценки сходства.
# --- Uniformity Metric for Base Model --- # Use the same diverse set of texts uniformity_embeddings_base = model.encode(uniformity_texts, convert_to_tensor=True) # Calculate all pairwise cosine similarities pairwise_cos_sim_base = util.cos_sim(uniformity_embeddings_base, uniformity_embeddings_base) # Extract unique pairwise similarities (excluding self-similarity and duplicates) upper_triangle_indices_base = torch.triu_indices(pairwise_cos_sim_base.shape[0], pairwise_cos_sim_base.shape[1], offset=1) uniformity_similarity_scores_base = pairwise_cos_sim_base[upper_triangle_indices_base[0], upper_triangle_indices_base[1]].cpu().numpy() # Calculate the average of these pairwise similarities average_uniformity_similarity_base = np.mean(uniformity_similarity_scores_base)И вот результаты. Учитывая очень ограниченный объем обучающих данных, использованных для тонкой настройки (всего 3 примера), неудивительно, что тонкая модель не демонстрирует явного улучшения по сравнению с базовой моделью по этим конкретным показателям.
Базовая модель располагала связанные элементы немного ближе друг к другу, чем ваша доработанная модель (более высокое выравнивание), а также располагала различные, не связанные между собой элементы немного дальше друг от друга или менее загроможденно, чем ваша доработанная модель (более низкая однородность).
* Base Model: Base Model Alignment Score (Avg Cosine Similarity of Positive Pairs): 0.8451 Base Model Uniformity Score (Avg Pairwise Cos Sim. of Diverse Embeddings): 0.0754 * Fine Tuned Model: Alignment Score (Average Cosine Similarity of Positive Pairs): 0.8270 Uniformity Score (Average Pairwise Cosine Similarity of Diverse Embeddings): 0.0777Прежде чем уйти
В этой статье мы на практике изучили встраивание моделей и принципы их работы.
Эти модели приобрели большое значение после бурного развития ИИ, став отличным инструментом для приложений RAG и быстрого поиска.
Компьютеры должны уметь понимать текст, и встраивание данных (эмбеддинги) играет в этом ключевую роль. Они кодируют текст в векторные представления чисел, что позволяет моделям легко вычислять расстояния и находить наилучшие совпадения.
Вот мои контактные данные, если вам понравился этот контент. Найдите меня на моем сайте.
https://gustavorsantos.me
Код на GitHub
https://github.com/gurezende/Studying/tree/master/Python/NLP/Embedding_Models
Ссылки
[1. Современная НЛП: токенизация, встраивание и классификация текста] (https://medium.com/data-science-collective/modern-nlp-tokenization-embedding-and-text-classification-448826f489bf?sk=6e5d94086f9636e451717dfd0bf1c03a)
[2. Визуальное руководство по первому использованию BERT] (https://jalammar.github.io/a-visual-guide-to-using-bert-for-the-first-time/)
[3. Документация Qdrant] (https://qdrant.tech/documentation/)
Густаво Сантос Посмотреть все Густаво Сантос
Источник: towardsdatascience.com






















