Вопросы для собеседования по воплощённому ИИ, набор 3, с ответами
1. Методология исследования и инженерная практика
На техническом собеседовании разбор статей и проектов обычно сосредоточен на логической замкнутости и инженерной реализуемости.
1. Ключевые моменты разбора статьи
- Мотивация исследования (Motivation): чётко объясните, почему выбран именно этот подход. Например, в стратегиях генерации действий одношаговая генерация (Single-step) даёт преимущество по задержке в управлении в реальном времени по сравнению со многошаговой авторегрессией (Autoregressive).
- Аблационные эксперименты (Ablation Study): проверка эффективности каждого модуля.
- Безопасность и устойчивость: например, механизмы защиты и построение данных для VLA-моделей (визуально-языково-действенных) при атаках, таких как Backdoor attacks.
- Подготовка к академической критике: заранее продумайте ответы о выборе baseline, границах обобщения и потерях при переносе Sim-to-Real.
2. Инженерия LLM и воплощённых систем
- Оптимизация вычислений: при развёртывании на симуляционных платформах (например, Isaac Lab/Gym) решите задачи ограниченной видеопамяти и эффективности параллельного сэмплирования.
- Извлечение признаков: использование таких методов, как разреженные автоэнкодеры (SAE), для анализа признаков.
- Оптимизация инференса: внедрение механизма поиска на этапе инференса (Inference-time search) для смягчения дрейфа инструкций (Instruction drift) при генерации длинных последовательностей моделью.
2. Базовая теоретическая библиотека знаний
1. Архитектура Transformer
-
Самовнимание (Self-Attention):
- Роль масштабирующего коэффициента : предотвращает насыщение softmax в области с исчезающими градиентами при слишком больших значениях скалярного произведения.
-
Позиционное кодирование с поворотом (RoPE):
Относительные позиционные отношения реализуются через поворот абсолютных позиций. Двумерная операция поворота:
2. Воплощённый ИИ и управление роботами
-
Модель контактной силы (управление импедансом):
- — коэффициенты жёсткости и демпфирования. Тактильные сигналы в мультимодальных моделях часто обрабатываются как эмбеддинги и выравниваются с аудио- и визуальными признаками.
-
Теорема о градиенте политики (Policy Gradient):
3. Генеративные модели: Flow Matching
Цель — регрессия оптимального векторного поля транспортировки от шума к данным :
- Линейный путь:
- Целевое векторное поле:
- Функция потерь:
3. Коллекция кода, который пишут на техническом собеседовании
1. Базовые компоненты глубокого обучения
Multi-Head Attention (с каузальной маской и коэффициентом температуры)
import torch
import torch.nn as nn
import math
class CausalTemperatureMHA(nn.Module):
def __init__(self, d_model: int, num_heads: int):
super().__init__()
self.num_heads = num_heads
self.d_k = d_model // num_heads
self.W_q = nn.Linear(d_model, d_model)
self.W_k = nn.Linear(d_model, d_model)
self.W_v = nn.Linear(d_model, d_model)
self.W_o = nn.Linear(d_model, d_model)
def forward(self, x, mask=None, temperature=1.0):
batch_size, seq_len, _ = x.size()
# Линейная проекция и разбиение на головы
Q = self.W_q(x).view(batch_size, seq_len, self.num_heads, self.d_k).transpose(1, 2)
K = self.W_k(x).view(batch_size, seq_len, self.num_heads, self.d_k).transpose(1, 2)
V = self.W_v(x).view(batch_size, seq_len, self.num_heads, self.d_k).transpose(1, 2)
# Масштабированное скалярное произведение внимания + коэффициент температуры
scores = torch.matmul(Q, K.transpose(-2, -1)) / (temperature * math.sqrt(self.d_k))
# Каузальная маска (Causal Mask)
causal_mask = torch.triu(torch.ones(seq_len, seq_len, device=x.device), diagonal=1).bool()
scores = scores.masked_fill(causal_mask, float('-inf'))
attn = torch.softmax(scores, dim=-1)
out = torch.matmul(attn, V).transpose(1, 2).contiguous().view(batch_size, seq_len, -1)
return self.W_o(out)
Реализация LayerNorm
class LayerNorm(nn.Module):
def __init__(self, shape, eps=1e-5):
super().__init__()
self.gamma = nn.Parameter(torch.ones(shape))
self.beta = nn.Parameter(torch.zeros(shape))
self.eps = eps
def forward(self, x):
mean = x.mean(dim=-1, keepdim=True)
var = x.var(dim=-1, unbiased=False, keepdim=True)
return self.gamma * (x - mean) / torch.sqrt(var + self.eps) + self.beta
2. Алгоритмы и типичные математические задачи
Квадратный корень методом бисекции (вещественные числа)
def mySqrt(x: float, epsilon: float = 1e-7) -> float:
if x < 0: return None
left, right = 0.0, max(x, 1.0)
while right - left > epsilon:
mid = (left + right) / 2
if mid * mid > x:
right = mid
else:
left = mid
return left
Два указателя: задача о сборе дождевой воды
1. Постановка задачи и цель
Описание задачи:
Дан неотрицательный целочисленный массив height, где каждый элемент — высота столбца в данной позиции, ширина всех столбцов равна 1. Вычислите, сколько единиц дождевой воды может удержаться между столбцами после дождя.
2. Основной физический принцип: эффект бочки (принцип самой короткой доски)
Чтобы определить, сколько воды удержится в позиции i, нужно знать максимальную высоту столбца слева и максимальную высоту столбца справа.
- Формула расчёта: объём воды в позиции = .
- Интуиция: вода стекает вниз, но сколько её удержится, определяется более низкой из двух боковых стенок (это и есть эффект бочки).
3. Построчный разбор логики кода
В приведённом коде используется оптимальный по памяти метод двух указателей:
def trap(height: list[int]) -> int:
# 1. Инициализация
left, right = 0, len(height) - 1 # Левый и правый указатели стоят на концах массива
l_max, r_max = 0, 0 # Максимальные высоты слева и справа, найденные при обходе
res = 0 # Общий объём
# 2. Обход
while left < right:
# Обновляем известные максимальные высоты слева и справа
l_max = max(l_max, height[left])
r_max = max(r_max, height[right])
# 3. Ключевое решение: обрабатываем сторону с меньшей высотой
if l_max < r_max:
# Если максимум слева меньше, значит слева «короткая доска»
# Тогда объём воды над height[left] полностью определяется l_max
res += l_max - height[left]
left += 1
else:
# Если максимум справа меньше или равен, короткая сторона — справа
res += r_max - height[right]
right -= 1
return res
Почему эта логика верна?
Когда выполняется l_max < r_max, мы можем не знать, есть ли справа от указателя left столбцы выше r_max. Но мы уже точно знаем: для текущей позиции left верхний предел удержания воды — это l_max. Поэтому можно спокойно посчитать объём в этой точке и сдвинуть указатель.
4. Анализ сложности
- Временная сложность:
- Массив обходится один раз: указатели
leftиrightсходятся к центру.
- Массив обходится один раз: указатели
- Пространственная сложность:
- Используются только константное число переменных (
l_max,r_max,resи т. п.), дополнительные массивы не нужны.
- Используются только константное число переменных (
5. Частые уточняющие вопросы на собеседовании
- Решение динамическим программированием: можно ли обменять память на время, не используя два указателя? (Да: предварительно вычислить массивы
left_maxиright_max, тогда пространственная сложность станет .) - Решение монотонным стеком: как решить эту задачу со стеком? (Поддерживая стек с убывающими высотами и вычисляя объём воды послойно.)
- Практическое применение: в компьютерном зрении и робототехнике логика поиска «промежутков между локальными экстремумами» часто используется для анализа рельефа по облакам точек лидара (LiDAR).
def trap(height: list[int]) -> int:
left, right = 0, len(height) - 1
l_max, r_max = 0, 0
res = 0
while left < right:
l_max = max(l_max, height[left])
r_max = max(r_max, height[right])
if l_max < r_max:
res += l_max - height[left]
left += 1
else:
res += r_max - height[right]
right -= 1
return res
Разберём пошагово на примере массива height = [4, 2, 0, 3, 2, 5].
1. Подготовка модели
- Начальное состояние:
left = 0(высота 4),right = 5(высота 5)l_max = 0,r_max = 0,res = 0
2. Пошаговое выполнение
Алгоритм перемещает левый и правый указатели, всегда обрабатывая «короткую доску», чтобы вычисленный объём воды был точным.
| Шаг | Положение указателей | Текущие высоты (h[l], h[r]) | Обновлённые максимумы (l_max, r_max) | Проверка условия и вычисление | Накопленный объём (res) | Далее |
|---|---|---|---|---|---|---|
| 1 | l=0, r=5 | 4, 5 | l_max=4, r_max=5 | l_max < r_max (4 < 5) истинно. res += 4 - 4 = 0 | 0 | left++ |
| 2 | l=1, r=5 | 2, 5 | l_max=4, r_max=5 | l_max < r_max (4 < 5) истинно. res += 4 - 2 = 2 | 2 | left++ |
| 3 | l=2, r=5 | 0, 5 | l_max=4, r_max=5 | l_max < r_max (4 < 5) истинно. res += 4 - 0 = 4 | 6 | left++ |
| 4 | l=3, r=5 | 3, 5 | l_max=4, r_max=5 | l_max < r_max (4 < 5) истинно. res += 4 - 3 = 1 | 7 | left++ |
| 5 | l=4, r=5 | 2, 5 | l_max=4, r_max=5 | l_max < r_max (4 < 5) истинно. res += 4 - 2 = 2 | 9 | left++ |
| Итог | l=5, r=5 | - | - | Условие цикла left < right больше не выполняется | 9 | - |
3. Итоги подсчёта
В этом примере фактический объём воды в позициях такой:
- Индекс 1:
- Индекс 2:
- Индекс 3:
- Индекс 4:
Итоговый объём удержанной воды:
Ключевой приём:
Когда
l_max < r_max, нам не нужно знать, сколько столбцов находится междуleftиright. Разr_maxуже большеl_max, то объём воды над позициейleftполностью определяется барьером слева —l_max.