Вопросы для собеседования инженера по мультимодальному машинному обучению
15 отобранных вопросов для собеседования по мультимодальному машинному обучению, сгруппированных по уровню seniority. Используйте их для повторения основ, практических компромиссов и рассуждений старших специалистов о производственных аспектах.
1Как контрастивное обучение согласует представления изображений и текста и зачем им общее пространство эмбеддингов?
Кодировщики изображения и текста переводят входы в одно векторное пространство. При обучении повышают сходство согласованных пар и понижают сходство несогласованных, например по косинусной мере. Затем можно искать изображения по тексту и подписи по изображению сравнением векторов. Для классификации без дообучения под задачу эмбеддинг изображения сравнивают с эмбеддингами текстовых описаний классов, например «фотография собаки», без отдельной классификационной головы для каждого набора классов.
import torch
import torch.nn.functional as F
# image_features: [B, D], text_features: [B, D]
image_norm = F.normalize(image_features, dim=-1)
text_norm = F.normalize(text_features, dim=-1)
# Pairwise cosine similarity matrix: [B, B]
sim_matrix = image_norm @ text_norm.T
# Positive pairs lie on the diagonal; off-diagonals are negatives
2Как работает архитектура с двумя кодировщиками в стиле CLIP и какое ограничение она накладывает на взаимодействие изображения и текста?
Отдельные сети, например ViT или ResNet для изображения и Transformer для текста, кодируют входы независимо. Они проецируют результаты в общее пространство и оценивают пару скалярным произведением нормированных векторов или косинусным сходством. На промежуточных слоях нет перекрёстного внимания между токенами и областями изображения: взаимодействие при оценке пары ограничено сходством итоговых векторов. Это позволяет заранее вычислить представления изображений и быстро искать по большому индексу, но затрудняет локализацию по отдельным словам и анализ сложных пространственных отношений.
3Зачем image/text-признаки проецируют в общее нормированное пространство и оптимизируют cosine?
L2-проекция на единичную гиперсферу отделяет семантическое направление от длины. Без неё свободный dot-product позволяет уменьшать loss раздуванием норм лёгких или частых примеров вместо согласования направлений. Cosine строго в пределах −1…1 и зависит от угла. Это убирает масштаб норм, но само не предотвращает collapse и не уравнивает градиенты примеров; negatives и objective дают дополнительную защиту. Обучаемая температура управляет остротой вероятностей, балансируя совпадение настоящих пар и равномерное распределение отрицательных.
import torch
import torch.nn.functional as F
# Unnormalized embeddings with extreme norm differences
v = torch.tensor([[10.0, 0.0], [0.1, 0.0]])
t = torch.tensor([[5.0, 0.0], [0.1, 0.0]])
# Raw dot products: heavily distorted by magnitude (50.0 vs 0.01)
raw_dot = v @ t.T
# L2 Normalized:
v_norm = F.normalize(v, p=2, dim=-1)
t_norm = F.normalize(t, p=2, dim=-1)
cosine_sim = v_norm @ t_norm.T
print('Cosine similarity matrix:\n', cosine_sim)
4Что такое привязка текста к области изображения и распознавание объекта по описанию (REC)? Чем они отличаются от оценки сходства целого изображения и текста?
Модель находит область изображения по естественному описанию, например человека в синей куртке рядом с фонарём. Для этого нужно различать объекты, их признаки и пространственные отношения. Результат — локализация, например ограничивающая рамка или маска. Оценка сходства возвращает общий балл для изображения и текста: кадр может подходить подписи «человек в парке», но балл не показывает, где этот человек и какой из нескольких объектов имеется в виду.
# Image-level similarity:
# Input: Image I, Text T ("black dog sitting on the left")
# Output: scalar score s in [0, 1] or dot product
similarity_score = image_text_model(image, text)
# Referring Expression Comprehension (Visual Grounding):
# Input: Image I, Text T ("black dog sitting on the left")
# Output: Bounding box coordinates [x_min, y_min, x_max, y_max]
bbox = grounding_model.predict_box(image, text)
5Как перекрёстное внимание объединяет визуальные и текстовые токены в мультимодальном трансформере?
Запросы Q формируются из одной последовательности, ключи K и значения V — из другой. Если Q получены из визуальных токенов, каждый из них получает взвешенную сумму текстовых значений: softmax(QKᵀ/√dₖ)V. Здесь dₖ — размерность ключа, а softmax применяется по текстовым позициям. Длины последовательностей могут различаться. Для двустороннего обмена применяют второй блок с обратным направлением или чередуют направления в нескольких блоках.
6Как обрезка, изменение цвета и сжатие изображения помогают или мешают контрастивному согласованию изображения с текстом?
Умеренные преобразования снижают зависимость от фона, водяных знаков и масштаба. В отличие от сопоставления двух вариантов одного изображения, здесь преобразованный кадр должен по-прежнему соответствовать подписи. Сильная обрезка может убрать упомянутую птицу, смена оттенка — превратить жёлтое такси в синее, а сжатие или размытие — скрыть надпись и мелкие детали. Такие пары дают неверный обучающий сигнал. Настраивайте силу аугментации по типу подписей и проверяйте результат на задачах поиска.
7Что такое поиск изображений по тексту и текста по изображениям и чем поиск в фиксированном наборе отличается от поиска по большой открытой коллекции?
По запросу одной модальности система ранжирует кандидатов другой, например сравнивая их эмбеддинги в общем пространстве. В фиксированном тестовом наборе кандидаты и эталонные пары заранее заданы; при малом размере можно сравнить все пары. В большой открытой коллекции состав меняется, есть похожие нерелевантные элементы и неразмеченные релевантные пары. Обычно кандидатов находят приближённым поиском ближайших соседей, например через индекс HNSW, а более дорогую модель оставляют для повторного ранжирования короткого списка.
import torch
import torch.nn.functional as F
# Closed-set matching: full pairwise similarity matrix over fixed evaluation set
image_embeds = F.normalize(torch.randn(1000, 512), dim=-1)
text_embeds = F.normalize(torch.randn(1000, 512), dim=-1)
sim_matrix = torch.matmul(text_embeds, image_embeds.T) # (1000, 1000)
# Open-world retrieval: query vector queried against an indexed corpus using ANN
# index = faiss.IndexHNSWFlat(512, 32)
# distances, indices = index.search(query_embed, k=10)
8Сравните InfoNCE-softmax и попарный sigmoid-loss обучения image/text-эмбеддингов.
CLIP-подобный InfoNCE — многоклассовая задача: softmax нормирует положительную и отрицательные пары по batch. SigLIP считает каждую ячейку матрицы независимой бинарной задачей с sigmoid и BCE: 1 положительным,0 отрицательным, либо эквивалентно ±1 в logistic loss. InfoNCE связывает negatives общим знаменателем, самые трудные доминируют градиент; sigmoid оценивает пары отдельно. Распределённый CLIP обычно собирает embeddings разных устройств ради negatives. SigLIP не требует глобального softmax и поддерживает расчёт частями, но cross-device-пары всё равно требуют обмена векторами. Эффективность и качество зависят от состава batch и обучения.
import torch
import torch.nn.functional as F
def siglip_loss(sim_matrix, temperature, bias):
# sim_matrix: [B, B] dot product of normalized embeddings
# targets: 1 on diagonal (positive), -1 on off-diagonals (negative)
B = sim_matrix.size(0)
targets = 2 * torch.eye(B, device=sim_matrix.device) - 1.0
logits = sim_matrix * temperature + bias
# Pairwise binary cross entropy with log-sigmoid
return -torch.mean(F.logsigmoid(targets * logits))
9Как сложные и ложноотрицательные пары влияют на контрастивное обучение изображений и текста?
Сложная отрицательная пара действительно не совпадает, хотя выглядит похожей, например фото хаски с подписью «аляскинский маламут». Она учит различать мелкие признаки. Ложноотрицательная пара на деле подходит, например другая фотография ретривера к общей подписи, но функция потерь отталкивает её как отрицательную. Это ухудшает представления и поиск. Помогают удаление дублей, обнаружение нескольких положительных соответствий и функции потерь, учитывающие неопределённость отрицательных меток.
import torch
import torch.nn.functional as F
# Image 0 and Image 1 both depict 'a red sports car'
# Text 0: 'a red sports car', Text 1: 'a fast red car'
# In standard InfoNCE, Text 1 is treated as a negative for Image 0.
sim = torch.tensor([[0.95, 0.90], # Image 0 similarities
[0.88, 0.94]]) # Image 1 similarities
loss_img0 = -F.log_softmax(sim / 0.07, dim=-1)[0, 0]
print(f'InfoNCE loss for Image 0: {loss_img0.item():.4f}')
# High similarity to false negative Text 1 (0.90) heavily penalizes the model
10Чем глобальное согласование изображения и текста отличается от согласования областей со словами или токенами?
Глобальная схема кодирует изображение и текст одним вектором на вход и согласует их, например через InfoNCE. Векторы удобно индексировать, но один вектор теряет часть сведений о количестве, пространстве и связи признака с объектом. Детальная схема сравнивает участки или области изображения со словами и их частями, например через максимум сходства токенов, оптимальный транспорт или перекрёстное внимание. Это полезно для локализации и сопоставления атрибутов, но увеличивает вычисления и память, а локальные соответствия могут быть шумными.
import torch
import torch.nn.functional as F
# visual_tokens: [B, N_v, D], text_tokens: [B, N_t, D]
def token_level_maxsim_similarity(visual_tokens, text_tokens):
v_norm = F.normalize(visual_tokens, dim=-1)
t_norm = F.normalize(text_tokens, dim=-1)
# Compute similarity matrix between all visual and text tokens: [B, N_t, N_v]
sim_matrix = torch.bmm(t_norm, v_norm.transpose(1, 2))
# Text-to-image: For each word token, find maximum visual token similarity and average
t2i_sim = sim_matrix.max(dim=-1).values.mean(dim=-1) # [B]
return t2i_sim
11Сравните раннее, промежуточное и позднее объединение модальностей, перекрёстное внимание, обучаемый выбор вклада и конкатенацию.
Раннее объединение подаёт токены обеих модальностей в общую сеть сразу: взаимодействие глубокое, но вычисления дороги. Промежуточное даёт отдельным сетям обработать вход до обмена признаками. Позднее сравнивает или объединяет итоговые векторы и удобно для индексируемого поиска. В перекрёстном внимании запросы одной модальности обращаются к ключам и значениям другой, даже при разной длине. Обучаемый затвор взвешивает вклад по контексту. Конкатенация соединяет признаки совместимой формы или последовательности токенов; обычное полное самовнимание на удлинённой последовательности имеет квадратичную стоимость.
12Чем модель с двумя кодировщиками отличается от совместного кодировщика для повторного ранжирования изображений и текста по точности, взаимодействию и задержке?
Два кодировщика независимо вычисляют векторы изображения и текста и сравнивают их. Векторы коллекции можно подготовить заранее и искать приближённо, но при таком сравнении нет взаимодействия отдельных слов и участков. Совместный кодировщик обрабатывает пару, позволяя токенам взаимодействовать через внимание. Это часто точнее при сложных атрибутах и пространственных отношениях, но совместную обработку приходится выполнять для каждой пары запроса и кандидата. Поэтому сначала обычно быстро находят кандидатов двумя кодировщиками, а затем повторно ранжируют короткий список совместной моделью.
13Спроектируйте мультимодальный RAG по PDF и руководствам с текстом, таблицами, графиками, скриншотами и изображениями.
1. Layout-aware LayoutLM/DocTR или vision-parser делит страницы на текст, таблицы с сохранением объединённых ячеек через HTML или другую структуру — обычный Markdown их не представляет, — графики с рядами и отдельные диаграммы/снимки с box. 2. Изображения храните crop с SigLIP/CLIP или ColPali patch-token и синтетическим описанием/OCR VLM в dense-text-index. Таблицы — structured Markdown/HTML в vector/BM25; текст — по разделам в dense и sparse. 3. Параллельно ищите BM25 по словам/OCR/таблице, text-vector и visual ANN. RRF объединяет; top ранжирует multimodal cross-encoder или late-interaction по high-res crop и тексту. 4. Top-k image-patch, схема таблицы и фрагменты с document/page передаются instruction-VLM, например GPT-4o, Claude3.5 Sonnet или Qwen2-VL. Prompt просит цитаты; код проверяет существование, доступ и поддержку утверждений document/page/region ID. Сохраняйте provenance через parsing/index, применяйте права до сборки, найденные инструкции считайте недоверенными данными.
from dataclasses import dataclass
from typing import Optional, List
@dataclass
class MultimodalChunk:
chunk_id: str
document_id: str
page_number: int
modality_type: str # 'text', 'table', 'chart', 'diagram'
text_payload: str # Raw text or structured Markdown/HTML
vlm_caption: Optional[str] = None # Synthetic summary of visual content
bbox: Optional[List[float]] = None # [x0, y0, x1, y1]
image_crop_path: Optional[str] = None
dense_embedding: Optional[List[float]] = None
# Indexing strategy: Text search covers text_payload + vlm_caption;
# Multimodal search matches dense_embedding or visual tokens.
14Как оценивать мультимодальную генерацию с поиском (RAG) отдельно по поиску, использованию подтверждений, ссылкам и итоговому ответу?
Для поиска измеряйте полноту и порядок релевантных страниц, фрагментов и областей, например Recall@K и NDCG@K, отдельно для текста, таблиц и графиков. Чтобы проверить использование материала, убирайте или заменяйте нужный фрагмент и проверяйте реакцию ответа; карта внимания сама этого не доказывает. Оценивайте, верны ли ссылки на документ, страницу и область и содержат ли они подтверждение. Для ответа отдельно измеряйте фактическую корректность и то, следуют ли утверждения из найденных источников. Проверяйте уместное воздержание при недостатке или конфликте данных.
# Evaluation record schema for a single Multimodal RAG query:
eval_record = {
'retrieval_quality': {
'hit_at_k': True, # Top-3 chunks contain target diagram
'visual_bbox_iou': 0.85 # Retrieved crop overlap with true figure region
},
'evidence_utilization': {
'necessity_ablation_passed': True # Removing chart causes answer to fail
},
'provenance': {
'page_match': True, # Cited Page 12 (Ground Truth Page 12)
'figure_id_match': True # Cited 'Figure 4'
},
'faithfulness': {
'claim_entailment_score': 1.0, # All claims entailed by context
'hallucination_detected': False
}
}
all_passed = all(all(metrics.values()) for metrics in eval_record.values())
print(f'System passes all decoupled checks: {all_passed}')
15Как обновлять мультимодальную систему поиска, если нужно пересчитать эмбеддинги большой коллекции и перестроить индекс?
Новый кодировщик обычно меняет пространство векторов, поэтому нельзя без проверки сравнивать его запросы со старой коллекцией. Постройте новый индекс отдельно, пока прежний обслуживает запросы. Догоняйте изменения и удаления двойной записью или журналом изменений. Проверьте полноту, задержку и актуальность в теневом режиме, затем согласованно переключите кодировщик и индекс. Сохраните прежнюю пару для отката. Если специально обучили совместимый кодировщик или адаптер, проверьте качество на старом индексе до поэтапного пересчёта.
class MultimodalRetrievalRouter:
def __init__(self, v1_service, v2_service, dual_write=True):
self.v1 = v1_service # Model v1 + Index v1
self.v2 = v2_service # Model v2 + Index v2
self.active_version = "v1"
self.dual_write = dual_write
def search(self, query_multimodal):
# Route query strictly to the encoder matching the active index
if self.active_version == "v1":
return self.v1.search(query_multimodal)
return self.v2.search(query_multimodal)
def ingest_new_item(self, item):
# Dual-write during migration window so the new index is up-to-date at cutover
self.v1.index_item(item)
if self.dual_write and self.v2.is_ready_for_ingest:
self.v2.index_item(item)