Сначала зафиксируйте grain данных, допущения, метрику и риск leakage, затем обсуждайте модель, инструмент или инфраструктуру.
Вопросы и ответы
12 подробных ответов
01Объясните backpropagation на концептуальном уровне. И почему нельзя инициализировать все веса нулями?
middle
Короткий ответ: Backpropagation — это chain rule (правило цепочки), применённое к вычислительному графу: forward pass кэширует активации, backward pass прогоняет градиент лосса от выхода к каждому весу. Нулевая инициализация ломает обучение из-за симметрии: все нейроны слоя получают одинаковые градиенты и навсегда остаются копиями друг друга.
Подробно:
- Forward pass — считаем выход и лосс, попутно сохраняя промежуточные активации: они понадобятся для производных.
- Backward pass — идём по графу в обратном порядке; градиент каждого узла = локальная производная × градиент сверху (chain rule).
- Обновление — шаг градиентного спуска по каждому весу.
- Симметрия при нулях — если все веса равны, у всех нейронов слоя одинаковые выходы и одинаковые градиенты → после любого числа шагов они идентичны, сеть эквивалентна одному нейрону на слой.
- Правильно — случайная инициализация: He для ReLU, Xavier для tanh/sigmoid.
x ──► h = f(W1·x) ──► ŷ = g(W2·h) ──► L
∂L/∂W1 = ∂L/∂ŷ · ∂ŷ/∂h · ∂h/∂W1 ← chain rule
⚠️ Частая ошибка: не суметь произнести «chain rule» или объяснить, почему нули убивает именно симметрия, а не «нулевые градиенты»: градиенты у слоя не нулевые — они одинаковые.
02Затухающие и взрывающиеся градиенты: откуда они берутся и какие стандартные способы борьбы?
middle
Короткий ответ: Градиент к ранним слоям — произведение многих якобианов. Если множители систематически меньше единицы (сатурация sigmoid/tanh, мелкие веса) — градиент затухает экспоненциально; если больше — взрывается. Стандартный арсенал: ReLU-семейство, He/Xavier-инициализация, BatchNorm/LayerNorm, residual-связи, gradient clipping.
Подробно:
- Механика — по chain rule градиент слоя k содержит произведение всех якобианов выше него: эффект экспоненциален по глубине.
- Сатурация — производная sigmoid ≤ 0.25, у tanh хвосты тоже плоские: глубокий стек из них почти гарантированно затухает.
- RNN — отдельная боль — одна и та же матрица умножается T раз по длине последовательности, поэтому взрывы там особенно типичны; стандарт — clipping по норме градиента.
| Причина | Фикс |
|---|---|
| Сатурация активаций | ReLU/GELU в скрытых слоях вместо sigmoid/tanh |
| Плохой масштаб весов | инициализация He (ReLU) / Xavier (tanh) |
| Дрейф распределений по глубине | BatchNorm / LayerNorm |
| Слишком длинный путь градиента | residual-связи (ResNet), гейты LSTM/GRU |
| Взрыв (особенно RNN) | gradient clipping |
⚠️ Частая ошибка: ответить одним пунктом «использовать ReLU». Интервьюер ждёт систему: активации + инициализация + нормализация + skip-связи — разные рычаги против одной и той же экспоненты.
03Как работает dropout и что с ним происходит на инференсе?
junior
Короткий ответ: На обучении dropout с вероятностью p зануляет случайные активации: каждый батч тренирует свою «прореженную» подсеть, что мешает ко-адаптации нейронов и работает как ансамбль подсетей. На инференсе dropout выключен; чтобы масштаб активаций совпал, используют inverted dropout — деление на (1−p) ещё на обучении.
Подробно:
- Механика — бинарная маска на активации, новая на каждый forward; нейрон не может полагаться на конкретных соседей и учит более робастные признаки.
- Интерпретация — обучение экспоненциального числа подсетей с общими весами; инференс ≈ усреднение этого ансамбля.
- Inverted dropout — активации делятся на (1−p) при обучении, поэтому на инференсе перевзвешивать ничего не нужно — слой просто отключается.
- Где ставить — обычно после полносвязных слоёв; в свёрточных сетях чаще заменяется BatchNorm и аугментациями.
drop = nn.Dropout(p=0.3)
model.train() # маска активна, деление на (1-p) уже внутри
model.eval() # dropout выключен: детерминированный инференс
⚠️ Частая ошибка: забыть про разницу train/inference (и про model.eval() в PyTorch): dropout, оставленный включённым на инференсе, даёт шумные предсказания.
04BatchNorm: что он делает на обучении и на инференсе, и почему вообще помогает?
senior
Короткий ответ: На обучении BatchNorm нормализует преактивации по статистикам текущего батча и применяет обучаемые масштаб и сдвиг γ/β, попутно обновляя бегущие средние. На инференсе батча может не быть — используются накопленные running mean/var, и слой становится детерминированной аффинной трансформацией. Помогает потому, что сглаживает ландшафт лосса и позволяет большие learning rate.
Подробно:
- Train — x̂ = (x − μ_batch)/√(σ²_batch + ε), затем y = γ·x̂ + β; γ и β учатся градиентным спуском, running-статистики обновляются экспоненциальным средним.
- Inference — те же формулы, но с running mean/var: предсказание не зависит от соседей по батчу.
- Почему работает — каноническая история про «internal covariate shift» оспорена (Santurkar et al., 2018): рабочее объяснение — сглаживание оптимизационного ландшафта → устойчивость к большим LR и к инициализации.
- Бонус — мягкая регуляризация: шум батчевых статистик действует как слабый dropout.
Классический follow-up: какие слои ведут себя по-разному в train и eval? — BatchNorm и dropout; отсюда обязательные model.train()/model.eval().
⚠️ Частая ошибка: уверенно продать «устранение internal covariate shift» как факт. Сильный ответ упоминает, что объяснение спорное, а эмпирика — большие LR и быстрая сходимость — бесспорна.
05BatchNorm против LayerNorm: где используется каждый и почему?
middle
Короткий ответ: BatchNorm нормализует каждый канал по батчу — его статистики зависят от соседей по батчу. LayerNorm нормализует признаки внутри одного примера — не зависит ни от размера батча, ни от длины последовательности. Поэтому BN — стандарт в CNN, а LN — в трансформерах и RNN.
Подробно:
- Оси нормализации — BN: усреднение по (N, H, W) отдельно для каждого канала; LN: усреднение по признакам одного сэмпла.
- Когда BN ломается — маленькие батчи (шумные статистики), переменная длина последовательностей, расхождение train/eval из-за running-статистик.
- Почему LN в трансформерах — одинаково работает для батча из 1 и из 1024, не тащит состояние (running stats) и дружит с автопрегрессивным инференсом токен за токеном.
| BatchNorm | LayerNorm | |
|---|---|---|
| Нормализует по | батчу, на канал | признакам, на сэмпл |
| Зависит от batch size | да | нет |
| Train vs inference | разное поведение (running stats) | одинаковое |
| Где стандарт | CNN | трансформеры, RNN |
| Маленькие батчи | ломается | ок |
⚠️ Частая ошибка: «LN — это просто BN, повернутый на 90°, разницы нет». Разница операционная: BN несёт состояние и связывает примеры внутри батча, LN — чистая функция от одного сэмпла.
06SGD, Momentum, Adam — что добавляет каждый следующий?
middle
Короткий ответ: SGD делает шаг по стохастическому градиенту. Momentum добавляет накопление скорости (экспоненциальное среднее градиентов) — гасит осцилляции и разгоняет движение по устойчивому направлению. Adam добавляет к momentum ещё и адаптивный learning rate на каждый параметр через оценку второго момента градиентов — поэтому он дефолт на практике.
Подробно:
- SGD — w ← w − lr·g; шумный, чувствителен к выбору lr и масштабу признаков.
- Momentum — v ← β·v + g, шаг по v: осцилляции поперёк «оврага» лосса взаимно гасятся, движение вдоль — накапливается.
- Adam — первый момент m (направление) + второй момент v (масштаб) → шаг m̂/√v̂: параметры с редкими или мелкими градиентами получают больший эффективный lr.
- Практика — Adam/AdamW как дефолт; SGD+momentum на vision-задачах иногда обобщает лучше при хорошем расписании lr.
| Оптимизатор | Что добавляет | Цена |
|---|---|---|
| SGD | — | чувствителен к lr |
| + Momentum | память направления | ещё один гиперпараметр β |
| Adam | + per-parameter адаптивный lr | иногда хуже обобщает |
Бонус для 🔴-уровня: в AdamW weight decay отвязан от адаптивного шага — L2-штраф внутри Adam не эквивалентен честному decay, поэтому AdamW и стал стандартом.
⚠️ Частая ошибка: произносить названия оптимизаторов как заклинания, не умея сказать, какую именно проблему решает каждая добавка.
07Почему в скрытых слоях используют ReLU, а не sigmoid?
junior
Короткий ответ: У sigmoid производная не больше 0.25 и почти нулевая на хвостах — глубокая сеть из сигмоид тонет в затухающих градиентах. У ReLU при x > 0 производная ровно 1: градиент проходит без сатурации; вдобавок ReLU считается копеечно, а половина нулевых активаций даёт разреженность.
Подробно:
- Градиенты — главный аргумент — нет сатурации на положительной полуоси → сигнал доходит до ранних слоёв даже в глубокой сети.
- Дёшево — max(0, x) против вычисления экспоненты.
- Разреженность — на каждом примере активна лишь часть нейронов.
- Каверза: dying ReLU — нейрон, улетевший в отрицательную зону, имеет нулевой градиент и может «умереть» навсегда → LeakyReLU или GELU (стандарт трансформеров).
| sigmoid | ReLU | |
|---|---|---|
| Производная | ≤ 0.25, сатурация с двух сторон | 1 при x>0, 0 при x<0 |
| Стоимость | экспонента | сравнение с нулём |
| Проблема | затухающие градиенты | dying ReLU |
| Где уместна | выходной слой (вероятность) | скрытые слои |
⚠️ Частая ошибка: ответить «так быстрее» или «так принято», не упомянув сатурацию градиентов — а это и есть ядро вопроса.
08Почему для изображений используют свёрточные сети, а не полносвязные? Что такое receptive field?
middle
Короткий ответ: Свёртка встраивает два приора изображений: локальность (пиксель связан с соседями) и weight sharing (один фильтр сканирует всю картинку). Отсюда эквивариантность к сдвигу и на порядки меньше параметров, чем у полносвязного слоя. Receptive field — область входа, которую «видит» один нейрон; он растёт с глубиной сети.
Подробно:
- Параметры — полносвязный слой от 224×224×3 к 1000 нейронам ≈ 150 млн весов; свёртка 3×3 с 3 до 64 каналов — меньше 2 тысяч.
- Эквивариантность к сдвигу — объект сдвинулся, карта признаков сдвинулась вместе с ним; полносвязной сети пришлось бы учить каждый сдвиг отдельно.
- Receptive field — растёт с каждым слоем: стек мелких свёрток покрывает ту же область, что один большой фильтр, но дешевле и с дополнительными нелинейностями.
- Мини-задача с собеседований — размер выхода свёртки: (n + 2p − k)/s + 1; её просят посчитать руками.
Вход 32×32, conv k=5, p=2, s=1: (32 + 4 − 5)/1 + 1 = 32
Вход 32×32, conv k=3, p=0, s=2: (32 − 3)/2 + 1 = 15
Receptive field: conv3×3 → conv3×3 = 5×5; ещё слой = 7×7
⚠️ Частая ошибка: плавать в формуле выходного размера — на собеседованиях её считают руками чаще, чем кажется.
09Какую проблему решают skip-связи в ResNet?
middle
Короткий ответ: Проблему деградации: глубокие «plain»-сети проигрывают мелким даже на трейне — это трудность оптимизации, а не переобучение и не только затухающие градиенты. Identity-shortcut даёт градиенту прямую магистраль назад, а слоям — задачу попроще: учить поправку F(x) = H(x) − x вместо всего отображения целиком.
Подробно:
- Симптом — 56-слойная plain-сеть хуже 20-слойной по train-ошибке (He et al., 2015); переобучением это объяснить нельзя.
- Residual-формулировка — блок выдаёт y = F(x) + x; выучить «ничего не делать» (F ≈ 0) тривиально, поэтому добавленная глубина как минимум не вредит.
- Градиентная магистраль — через shortcut градиент течёт к ранним слоям напрямую, минуя произведение якобианов.
- Следствие — стали обучаемыми сети на 100+ слоёв; идея переехала в трансформеры: residual вокруг attention и FFN-блоков.
x ──► [conv → BN → ReLU → conv] ──► F(x) ──(+)──► ReLU ──►
└────────────────── identity ──────────────┘
⚠️ Частая ошибка: свести всё к «борьбе с затуханием градиентов». BatchNorm в plain-сетях уже держит градиенты живыми — деградация именно оптимизационная, и residual чинит её.
10Когда выбрать глубокое обучение, а когда градиентный бустинг?
middle
Короткий ответ: Табличные данные умеренного объёма — бустинг (XGBoost/LightGBM/CatBoost): на таблицах он по бенчмаркам всё ещё стабильно обыгрывает нейросети, дешевле в обучении и проще в интерпретации. Deep learning берём для неструктурированных данных (текст, картинки, аудио), очень больших объёмов и там, где нужны эмбеддинги, transfer learning или multi-task.
Подробно:
| Критерий | Бустинг | Deep learning |
|---|---|---|
| Табличные данные | дефолт, топ бенчмарков | догоняет редко |
| Текст/картинки/аудио | нужен ручной feature engineering | учит представления сам |
| Объём данных | работает и на 10⁴ строк | раскрывается на больших |
| Стоимость | минуты на CPU | GPU, тюнинг, инфраструктура |
| Интерпретируемость | feature importance, SHAP | заметно сложнее |
| Transfer / multi-task | нет | эмбеддинги, дообучение |
- Практическое правило — даже если план — нейросеть, начать с бустинга как бейзлайна: он задаёт планку и вскрывает проблемы данных.
- Гибриды — эмбеддинги из нейросети как фичи в бустинг — типовой продакшн-паттерн.
⚠️ Частая ошибка: «нейросети всегда сильнее». Интервьюер слушает прагматизм: выбор по типу данных, объёму и бюджету, а не по хайпу.
11Что такое эмбеддинг?
junior
Короткий ответ: Эмбеддинг — обучаемый плотный вектор, представляющий дискретный объект (слово, товар, пользователя, категорию) так, что геометрия пространства кодирует смысловую близость: похожие объекты лежат рядом. Это и способ скормить категориальное нейросети, и готовый инструмент поиска похожего.
Подробно:
- Против one-hot — one-hot разреженный, размерности словаря, и все объекты в нём равноудалены; эмбеддинг плотный, низкоразмерный, и расстояния в нём осмысленны.
- Откуда берётся — либо учится вместе с основной задачей (nn.Embedding), либо берётся предобученный: word2vec, слои BERT, CLIP.
- Зачем на практике — генерация кандидатов в рекомендациях (ANN-поиск ближайших соседей), семантический поиск, дедупликация, фичи для бустинга, transfer learning.
emb = nn.Embedding(num_embeddings=50_000, embedding_dim=64)
v = emb(token_ids) # [batch, seq, 64] — плотные вектора
# похожесть = cosine similarity между векторами
⚠️ Частая ошибка: дать определение и не назвать ни одного конкретного применения. «Кандидаты в рекомендациях через поиск ближайших соседей по эмбеддингам» — уже достаточный ответ.
12Как ускорить инференс нейросети в продакшене?
senior
Короткий ответ: Стандартный арсенал: квантизация (fp16/int8), прунинг, дистилляция (компактный student учится у большого teacher), компиляция под железо (ONNX Runtime/TensorRT), батчинг запросов и кэширование эмбеддингов. И помнить: инференс сам по себе легче обучения — он не хранит активации и состояние оптимизатора, поэтому обучение ест в ~3–4 раза больше памяти.
Подробно:
| Техника | Что делает | Цена |
|---|---|---|
| Квантизация | fp32 → fp16/int8 | небольшая потеря качества; int8 требует калибровки |
| Прунинг | зануление незначимых весов | ускоряет только structured-разреженность |
| Дистилляция | student имитирует выходы teacher | отдельный цикл обучения |
| Компиляция | ONNX/TensorRT: fusion слоёв под GPU | привязка к железу |
| Батчинг | амортизирует overhead на запрос | растёт латентность хвоста |
| Кэш эмбеддингов | не пересчитывать повторяющееся | инвалидация, память |
- Порядок действий — сначала профилировать: узким местом часто оказывается препроцессинг или сеть, а не сама модель.
- Память — на инференсе нет backward: не храним активации, градиенты и моменты Adam.
⚠️ Частая ошибка: предложить «взять GPU помощнее». Интервьюер ждёт арсенал техник и понимание trade-off качества/скорости у каждой.
Источники
Источники и редакционная политика
Материалы RecallDeck сопоставлены с официальной документацией и открытыми публикациями компаний, когда первичный источник доступен. Мы не связаны с упомянутыми работодателями, не публикуем конфиденциальные задания и не продаём места в подборках. Формат найма может меняться — уточняйте его у рекрутера.
От чтения к воспроизведению
Отрепетируйте полный цикл интервью.
RecallDeck возвращает сложные темы по расписанию и помогает удерживать в памяти язык, SQL, архитектуру и поведенческие истории.