Transfer Learning 🔄
Задай себе честный вопрос: сколько данных нужно, чтобы с нуля обучить сверточную сеть, которая уверенно отличает фотографии здоровой кожи от подозрительных родинок, или сеть, которая по рентгеновскому снимку находит признаки пневмонии? Ответ, если строить сеть с нуля, — десятки, а лучше сотни тысяч размеченных изображений и дни обучения на кластере GPU. У подавляющего большинства реальных проектов таких данных просто нет: медицинская клиника располагает парой тысяч снимков, стартап с распознаванием дефектов на конвейере — несколькими сотнями фотографий брака, а у тебя лично для пет-проекта в лучшем случае найдётся датасет из полутора тысяч картинок, наспех собранных за выходные. Transfer learning (перенос обучения) — это ответ на вопрос, что делать в этой ситуации, и одновременно, пожалуй, самая практически применимая техника из всего блока Deep Learning этого курса.
Идея на удивление проста и от этого не менее мощна: вместо того чтобы обучать модель с нуля на своих скромных данных, ты берёшь модель, которая уже обучена кем-то другим на огромном стороннем датасете — например, ResNet50, обученную на 1,2 миллионах изображений ImageNet, — и адаптируешь её под свою задачу. Не переизобретаешь распознавание краёв, текстур и форм заново — берёшь сеть, которая это уже умеет, и учишь её лишь тому специфичному, что отличает именно твою задачу от задачи, на которой сеть обучалась изначально. Одна строчка кода в PyTorch,
import torchvision.models as models
model = models.resnet50(pretrained=True)
— и ты держишь в руках сеть, на обучение которой у её авторов ушли недели вычислений на профессиональном кластере, а тебе она досталась бесплатно и за секунды загрузки весов.
Именно поэтому в реальной практике Data Science подавляющее большинство успешных проектов компьютерного зрения не обучают модель с нуля. Обучение с нуля (from scratch) сегодня — это скорее исключение, оправданное либо очень специфичным доменом данных (спутниковые снимки в нестандартных спектральных каналах, медицинская визуализация с уникальной физикой сигнала), либо ролью исследователя, разрабатывающего новую архитектуру как таковую. Практикующий инженер, которому нужно решить конкретную бизнес-задачу за разумное время и с разумным бюджетом на разметку данных, почти всегда начинает с предобученной модели. То же самое сегодня верно и для текста: почти никто не обучает языковую модель с нуля под задачу тональности отзывов или классификации обращений в поддержку — берут BERT или GPT (урок 344) и дообучают.
Сегодняшний урок разберёт, почему перенос обучения вообще работает — что именно позволяет знаниям, накопленным сетью на одной задаче, оказаться полезными для совершенно другой задачи, — и два основных практических подхода к переносу: заморозить предобученную сеть и обучить поверх неё только новый слой (feature extraction), либо разморозить часть или все веса и аккуратно дообучить всю сеть на своих данных (fine-tuning). Мы разберём, как выбрать между этими подходами на основе размера своего датасета и его похожести на исходную задачу предобучения, и увидим, как ровно та же самая идея переноса лежит в основе NLP-революции последних лет через BERT и GPT.
История
Идея не начинать обучение "с чистого листа" существенно старше глубокого обучения и восходит к более широкой области машинного обучения — к так называемому multi-task learning и inductive transfer девяностых годов, где исследователи задавались вопросом: может ли знание, полученное при решении одной задачи, ускорить или улучшить решение другой, связанной задачи? Систематизирующий обзор области — статья Синно Джиалин Пана и Цян Яна "A Survey on Transfer Learning" (2010) — впервые аккуратно разложил перенос обучения по полочкам: какие бывают виды переноса, когда домен источника и домен цели совпадают, а когда различаются, какие задачи решает индуктивный, трансдуктивный и неконтролируемый перенос. Но по-настоящему массовым и практически неизбежным инструментом transfer learning стал именно с приходом глубоких сверточных сетей и датасета ImageNet.
Переломный момент наступил вскоре после триумфа AlexNet на конкурсе ImageNet в 2012 году (урок 335). Уже в 2014 году вышла работа Джейсона Йосински, Джеффа Клуна, Йошуа Бенджио и Хода Липсона "How transferable are features in deep neural networks?" — прямое экспериментальное исследование того самого вопроса, который сегодня и является ядром этого урока: если взять сеть, обученную на ImageNet, и переставить её слои на совершенно другую задачу классификации изображений, какие слои перенесутся хорошо, а какие потребуют переобучения? Авторы показали ровно то, что интуитивно предполагали инженеры и что мы разберём в следующем разделе: первые слои сети выучивают признаки настолько общие (грани, цветовые пятна, простые текстуры), что они прекрасно работают даже на совершенно незнакомых сети категориях изображений, тогда как последние слои становятся всё более специфичными именно для тех 1000 классов ImageNet, на которых сеть обучалась.
Эта находка вместе с бурным ростом числа доступных предобученных моделей — VGG, ResNet (урок 337), Inception и EfficientNet (урок 338) — превратила transfer learning из академического любопытства в инженерный стандарт по умолчанию. Библиотеки вроде torchvision в PyTorch и keras.applications в TensorFlow стали поставлять веса, обученные на ImageNet, буквально "из коробки", одной строчкой кода. Параллельно, ближе к концу 2010-х годов, та же самая идея была заново открыта и доведена до предела в области обработки естественного языка: ELMo (2018), а затем BERT и GPT (урок 344) показали, что языковую модель, предобученную на огромном корпусе неразмеченного текста, можно дообучить под практически любую конкретную задачу NLP за считаные часы на одной видеокарте — там, где обучение сопоставимой модели с нуля потребовало бы недель и корпуса, который просто негде взять. Сегодня transfer learning — это не отдельная "продвинутая" техника, а стандартная отправная точка почти любого прикладного проекта глубокого обучения.
Идея переноса обучения: почему ранние слои универсальны
Интуиция
Вернись мысленно к уроку 326, где мы разбирали, что глубина сети — это не просто "больше параметров", а механизм построения иерархии признаков: ранние слои сети выучивают простые, локальные, универсальные паттерны — грани определённой ориентации, цветовые градиенты, простые текстуры, — а более глубокие слои комбинируют их во всё более сложные и специфичные структуры — части объектов, а затем и целые объекты. В уроке 335 мы увидели эту же иерархию буквально, на конкретных фильтрах свёрточной сети: первый свёрточный слой реагирует на то же самое, на что реагировал классический фильтр Собеля — на вертикальные и горизонтальные перепады яркости, — а самые глубокие слои реагируют уже на присутствие целых узнаваемых категорий (собака определённой породы, автомобиль, лицо).
Здесь и кроется ключевое наблюдение, лежащее в основе всего transfer learning: признак "вертикальный край" или "текстура меха" не специфичен для задачи "различить 1000 классов ImageNet". Он одинаково полезен и для того, чтобы отличить кошку от собаки, и для того, чтобы отличить здоровую родинку от подозрительной, и для того, чтобы найти трещину на детали конвейера. Грани, углы, текстуры, цветовые пятна, простые геометрические формы — это фундаментальный, предметно-независимый "алфавит" визуального мира, из которого складывается практически любая задача компьютерного зрения. Сеть, которая один раз выучила этот алфавит на миллионе размеченных фотографий ImageNet, не обязана переучивать его заново для твоей задачи — она уже умеет "видеть" в этом базовом смысле, и остаётся научить её лишь тому специфичному словарю, который отличает именно твои классы.
Чем глубже слой, тем более специфичным для исходной задачи предобучения он становится: последние сверточные слои ResNet50, обученной на ImageNet, настроены распознавать, скажем, характерные текстуры меха 120 разных пород собак — признак крайне специфичный именно для задачи ImageNet и куда менее полезный, если твоя задача — классификация промышленного брака на металлической поверхности. Именно эта закономерность — "ранние слои универсальны, поздние слои специфичны" — и есть математический и эмпирический фундамент, на котором строятся оба практических подхода к переносу, которые мы разберём в следующем разделе.
Формальное определение
Transfer learning (перенос обучения). Пусть модель $f_\theta$ с параметрами $\theta$ обучена решать исходную задачу (source task) на исходном датасете $D_{source}$ — как правило, очень большом (например, ImageNet, 1,2 млн изображений, 1000 классов, или корпус текста в десятки миллиардов слов для языковых моделей). Перенос обучения — это использование параметров $\theta$, уже подобранных при решении исходной задачи, в качестве отправной точки (а не случайной инициализации) для решения целевой задачи (target task) на целевом датасете $D_{target}$, который, как правило, значительно меньше $D_{source}$ и может относиться к другому, но связанному домену. Формально перенос эффективен ровно в той мере, в какой признаки, выученные функцией $f_\theta$ на ранних слоях при решении source task, остаются полезными (информативными, статистически связанными с целевой переменной) при решении target task — а эмпирически (Yosinski et al., 2014) это верно для широкого класса задач компьютерного зрения именно потому, что ранние слои кодируют признаки общего, а не узкоспециализированного характера.
Разбор примеров
Пример 1 (перенос между визуально похожими задачами). У тебя есть сеть ResNet50, обученная на ImageNet, где среди 1000 классов присутствуют десятки пород собак и кошек, автомобили, разные бытовые предметы. Тебе нужно построить классификатор пород собак для приюта животных — 37 конкретных пород, датасет из 3700 фотографий. Задача очень похожа на исходную: и там, и там речь о естественных фотографиях животных с похожей текстурой меха, похожими формами ушей и мордочек. В этом случае почти все выученные признаки — от границ и текстур до частей объектов вроде "ухо" и "глаз" — напрямую переносятся, и тебе нужно лишь заново научить сеть финальному различению 37 конкретных пород вместо исходных 1000 классов.
Пример 2 (перенос между слабо похожими задачами). Та же ResNet50, обученная на ImageNet, применяется для классификации гистологических срезов ткани под микроскопом на предмет злокачественности. Здесь домены визуально куда дальше друг от друга: микроскопические изображения тканей не похожи на фотографии из повседневной жизни ни по цветовой палитре, ни по характерным текстурам, ни по масштабу деталей. Тем не менее перенос всё равно работает — просто в меньшей степени и требует больше "донастройки". Самые ранние слои (грани, простые градиенты яркости) остаются полезными почти всегда, поскольку любое цифровое изображение состоит из перепадов яркости независимо от домена, а вот средние и поздние слои, "заточенные" под текстуры меха и форму бытовых предметов, окажутся куда менее релевантны и потребуют существенного дообучения или полной замены.
Пример 3 (перенос между принципиально разными типами данных не работает напрямую). Возьми ту же ResNet50 и попробуй применить её как есть к задаче предсказания цены квартиры по табличным признакам (площадь, этаж, район) — задаче из блока классического ML этого курса (уроки 310–318). Перенос здесь не сработает вообще, и дело не в размере датасетов, а в самой природе данных: сверточные фильтры ResNet устроены так, чтобы находить пространственные, локальные паттерны в двумерной сетке пикселей, — у табличных данных попросту нет той пространственной структуры (соседние столбцы таблицы обычно не связаны так, как соседние пиксели изображения), на которую рассчитаны эти фильтры. Transfer learning требует не просто "какой-то похожести задач вообще", а совпадения по типу и структуре входных данных — изображение переносится на изображение, текст переносится на текст, но не изображение на табличные данные.
Почему это важно
Понимание того, почему именно ранние слои универсальны, а поздние специфичны, — это не абстрактная теория, а прямое практическое руководство к действию: именно эта закономерность определяет, сколько слоёв предобученной сети стоит замораживать, а сколько дообучать, и именно на ней строится вся логика выбора между feature extraction и fine-tuning, к которым мы переходим в следующем разделе. Без понимания иерархии признаков (уроки 326, 335) решение "заморозить первые 100 слоёв, а последние 20 дообучить" выглядело бы произвольным волшебным числом; с этим пониманием оно становится осмысленным инженерным выбором, основанным на том, какие именно признаки требуются твоей конкретной задаче.
Feature Extraction и Fine-Tuning: два пути адаптации
Интуиция
Раз ранние слои сети уже умеют распознавать универсальные визуальные примитивы, а поздние — специфичны для исходной задачи, у тебя на практике есть ровно два разумных способа адаптировать предобученную сеть под свою задачу, и разница между ними — это, по сути, вопрос "сколько из уже выученного я разрешаю сети менять".
Первый способ, feature extraction (извлечение признаков), — самый экономный: ты замораживаешь абсолютно все веса предобученной сети (запрещаешь им изменяться при обучении), удаляешь исходный последний слой (который в ResNet50 выдавал 1000 вероятностей классов ImageNet) и приделываешь вместо него новый, случайно инициализированный слой под число классов именно твоей задачи. Обучается — то есть подстраивается градиентным спуском — только этот новый последний слой; вся остальная сеть используется просто как неизменный "калькулятор признаков", который на вход принимает изображение, а на выходе выдаёт вектор чисел, описывающий его содержимое на высоком уровне абстракции.
Второй способ, fine-tuning (тонкая настройка), идёт дальше: ты не просто добавляешь новый последний слой, а размораживаешь часть или все веса предобученной сети и позволяешь им тоже немного измениться в процессе обучения на своих данных — но обязательно с сильно уменьшенным шагом обучения (learning rate) по сравнению с тем, что использовался при исходном обучении на ImageNet. Идея в том, чтобы не портить уже накопленные полезные знания резкими, большими шагами градиентного спуска, а лишь аккуратно "подкрутить" веса, сдвинув их чуть ближе к тому, что нужно именно твоей задаче.
Формальное определение
Feature extraction (извлечение признаков). Пусть предобученная сеть представлена как композиция "тела" (backbone) $g_\phi$ — всех слоёв вплоть до последнего — и "головы" (head) $h_\psi$ — финального классификационного слоя. При feature extraction параметры тела $\phi$ фиксируются (
requires_grad = False, градиенты по ним не вычисляются и не обновляются), исходная голова $h_\psi$ отбрасывается и заменяется новой головой $h_{\psi'}$ со случайной инициализацией и нужным числом выходов, после чего обучается только $\psi'$ путём минимизации функции потерь на целевом датасете, при этом $\phi$ на протяжении всего обучения остаётся равным ровно тем значениям, что были получены при предобучении.Fine-tuning (тонкая настройка). При fine-tuning параметры тела $\phi$ не фиксируются, а продолжают обучаться вместе с параметрами новой головы $\psi'$, однако с существенно меньшим шагом обучения, чем при исходном предобучении (типично в 10–100 раз меньше), и часто не сразу, а по расписанию: некоторое число эпох сеть обучается в режиме feature extraction (только голова), а затем часть или все слои тела размораживаются и дообучаются совместно с уже "прогретой" головой на малом шаге обучения.
Разбор примеров
Пример 1 (feature extraction — маленький датасет, похожая задача). У тебя 800 фотографий, задача — отличить 5 видов комнатных растений для мобильного приложения, задача визуально очень близка к тому, чему училась ImageNet-сеть (там тоже были классы растений). Код на PyTorch выглядит так:
import torch
import torch.nn as nn
import torchvision.models as models
model = models.resnet50(pretrained=True)
# Замораживаем все веса backbone
for param in model.parameters():
param.requires_grad = False
# Заменяем последний слой под свою задачу (5 классов)
num_features = model.fc.in_features
model.fc = nn.Linear(num_features, 5)
# У нового слоя requires_grad=True по умолчанию — учиться будет только он
optimizer = torch.optim.Adam(model.fc.parameters(), lr=1e-3)
На датасете в 800 изображений такое обучение занимает считаные минуты даже на слабой видеокарте, потому что градиенты вычисляются и хранятся только для последнего слоя из нескольких тысяч параметров, а не для всех 25 миллионов параметров ResNet50.
Пример 2 (fine-tuning всей сети — датасет побольше, задача чуть менее похожая). У тебя 15 000 фотографий дефектов на печатных платах, задача уже заметно отличается от повседневных фотографий ImageNet текстурой и масштабом деталей. Здесь одного нового слоя недостаточно — стоит разморозить всю сеть, но обучать её с маленьким шагом обучения, а лучше — с разными шагами обучения для разных частей сети: этот приём называется дифференцированными шагами обучения (differential learning rates):
model = models.resnet50(pretrained=True)
num_features = model.fc.in_features
model.fc = nn.Linear(num_features, 2) # брак / норма
# Размораживаем всё
for param in model.parameters():
param.requires_grad = True
# Разные шаги обучения: тело сети учится осторожно, голова — активнее
optimizer = torch.optim.Adam([
{"params": model.fc.parameters(), "lr": 1e-3},
{"params": (p for n, p in model.named_parameters() if "fc" not in n), "lr": 1e-5},
])
Такое обучение медленнее и требовательнее к объёму данных, чем чистый feature extraction, но даёт заметно более высокую точность, если датасета достаточно, чтобы предобученные веса действительно нашли, куда именно им сдвинуться под новую текстуру и специфику дефектов на плате.
Пример 3 (частичная заморозка — компромисс между двумя крайностями). Наиболее распространённый на практике вариант — не крайний feature extraction и не fine-tuning всей сети целиком, а нечто среднее: заморозить первые несколько блоков сети (те, что отвечают за универсальные признаки — грани, текстуры), а разморозить только последние один-два блока вместе с новой головой:
model = models.resnet50(pretrained=True)
# Замораживаем всё, кроме последнего блока (layer4) и головы
for name, param in model.named_parameters():
if "layer4" not in name and "fc" not in name:
param.requires_grad = False
num_features = model.fc.in_features
model.fc = nn.Linear(num_features, num_classes)
optimizer = torch.optim.Adam(
filter(lambda p: p.requires_grad, model.parameters()), lr=1e-4
)
Этот вариант — типичный практический компромисс для задач среднего размера: он позволяет дообучить именно те, более специфичные признаки последних слоёв, которые сильнее всего завязаны на конкретику исходной задачи ImageNet, оставляя нетронутым фундамент из универсальных ранних признаков, о котором шла речь в предыдущем разделе.
Почему это важно
Выбор между feature extraction и fine-tuning — не вопрос личного вкуса, а вопрос конкретного компромисса между риском переобучения на маленьком датасете и способностью модели адаптироваться к специфике твоей задачи. Заморозка всей сети (feature extraction) резко снижает число обучаемых параметров, а вместе с ним и риск переобучения на маленьком датасете, но ограничивает модель тем набором признаков, что уже был выучен на чужой задаче. Разморозка всей сети (полный fine-tuning) даёт максимальную гибкость подстройки, но с маленьким датасетом легко приводит к катастрофическому забыванию — ситуации, когда веса, изначально кодировавшие полезные универсальные признаки, "съезжают" в сторону переобучения на нескольких сотнях примеров и теряют то самое качество, ради которого их вообще имело смысл заимствовать. Именно поэтому следующий раздел формализует практическое правило: как именно размер своего датасета и похожесть задачи на исходную задачу предобучения определяют, какую из этих стратегий (или их промежуточный вариант) стоит выбрать.
Как выбрать подход: практическое правило по размеру датасета
Интуиция
За выбором между feature extraction, частичной разморозкой и полным fine-tuning стоит на самом деле всего два вопроса, которые стоит задать себе перед тем, как писать код: во-первых, сколько у меня размеченных данных, и во-вторых, насколько моя задача похожа на ту, на которой сеть обучалась изначально (для сетей из torchvision — это, как правило, ImageNet: естественные цветные фотографии повседневных объектов, животных, транспорта, бытовых предметов). Ответы на эти два вопроса образуют простую практическую матрицу решений, которую стоит держать в голове перед любым проектом переноса обучения.
Логика здесь прямо следует из того, что мы уже разобрали: чем меньше данных, тем выше риск, что размороженные веса "переобучатся" — подстроятся под шум конкретных нескольких сотен примеров, а не под настоящую закономерность, — поэтому при маленьком датасете стоит замораживать как можно больше слоёв. И чем менее твоя задача похожа на исходную задачу предобучения, тем больше слоёв — особенно поздних, специфичных — стоит разморозить и дообучить, потому что признаки, полезные для ImageNet, попросту не подходят один в один для гистологических срезов тканей или спутниковых снимков.
Формальное определение
Практическая матрица выбора стратегии переноса. Стратегия адаптации предобученной сети определяется двумя факторами: размером целевого датасета (малый / большой) и степенью похожести целевой задачи на задачу предобучения (похожая / непохожая). Комбинация этих двух факторов задаёт четыре типичных сценария:
| Размер датасета | Похожа на исходную задачу | Не похожа на исходную задачу |
|---|---|---|
| Маленький (сотни — единицы тысяч примеров) | Feature extraction: заморозить всё тело сети, обучить только новую голову | Feature extraction на ранних/средних слоях + попытка обучить голову поверх ранних признаков; риск переобучения высок в любом случае, стоит рассмотреть дополнительно data augmentation |
| Большой (десятки тысяч примеров и более) | Fine-tuning последних блоков (или всей сети) с маленьким шагом обучения — можно дообучать смело | Fine-tuning всей сети с маленьким шагом обучения, возможно, с более длительным обучением; в крайних случаях (данные совсем другой природы) может понадобиться обучение с нуля |
Разбор примеров
Пример 1 (маленький датасет, похожая задача — золотой случай feature extraction). Классификатор из 5 пород собак для приюта, 600 фотографий. Датасет маленький, задача очень похожа на ImageNet (там уже есть десятки пород собак). Это ровно та ячейка матрицы, где feature extraction не просто допустим, а оптимален: замораживаем весь backbone, обучаем только последний линейный слой, ожидаем точность в районе 90%+ буквально за несколько минут обучения на CPU. Попытка разморозить всю сеть здесь скорее навредит — 600 изображений на 25 миллионов параметров ResNet50 почти гарантированно приведут к переобучению.
Пример 2 (большой датасет, похожая задача — можно дообучать смело). Тот же тип задачи (распознавание пород животных), но датасет вырос до 80 000 фотографий — например, за счёт сбора данных с нескольких приютов страны за годы. Похожесть на исходную задачу та же, но теперь данных достаточно, чтобы позволить себе fine-tuning: размораживаем последние два-три блока сети (или всю сеть целиком) и дообучаем с маленьким шагом обучения порядка $10^{-5}$–$10^{-4}$. Ожидаемый выигрыш по точности по сравнению с чистым feature extraction — несколько процентных пунктов, и на таком объёме данных риск переобучения при полном fine-tuning уже приемлем.
Пример 3 (маленький датасет, непохожая задача — самый трудный случай). Классификация аэрофотоснимков сельскохозяйственных полей по типу культуры, всего 400 снимков (получение спутниковых данных с разметкой — дорого и медленно), задача заметно отличается от ImageNet и по цветовой гамме (часто это не RGB, а комбинации спектральных каналов), и по масштабу объектов (вид сверху, без привычной перспективы). Это самый трудный сценарий матрицы: данных мало, а перенос признаков ограничен из-за непохожести доменов. Практический выход здесь — комбинация подходов: заморозить только самые ранние 1–2 блока (где признаки — просто грани и цветовые градиенты, они универсальны почти всегда, независимо от домена), разморозить и аккуратно дообучить средние и поздние блоки с очень маленьким шагом обучения, дополнить это агрессивным data augmentation (повороты, отражения, случайная обрезка) — искусственно "размножить" ограниченный датасет — и по возможности собрать хотя бы ещё немного дополнительных размеченных примеров, прежде чем ожидать production-качества модели.
Почему это важно
Матрица "размер датасета × похожесть задачи" — это не строгая математическая теорема, а проверенное временем практическое правило, которое экономит недели впустую потраченных экспериментов: вместо того чтобы наугад перебирать "разморозить всё / разморозить ничего / разморозить половину", ты сразу сужаешь пространство разумных стратегий до одной-двух и начинаешь с неё, подстраивая детали (сколько именно блоков разморозить, какой конкретно шаг обучения выбрать) уже по фактическим метрикам на валидации. Именно это умение — быстро определить, в какой ячейке матрицы находится твоя реальная задача, и выбрать соразмерную стратегию — отличает практика, который эффективно использует ограниченное время и вычислительный бюджет, от того, кто наугад запускает то feature extraction, то полный fine-tuning, не понимая, почему один подход сработал, а другой — нет.
Transfer Learning в NLP: BERT, GPT и языковые модели как база знаний
Интуиция
Ровно та же самая идея, которую мы разобрали на примере изображений — предобучить модель на огромном стороннем датасете, а затем дообучить её на маленьком целевом датасете, — легла в основу революции в обработке естественного языка, о которой шла речь в уроке 344. Разница лишь в том, что там источником "универсальных признаков" служит не ImageNet, а колоссальный корпус неразмеченного текста — практически весь текст, который удалось собрать из интернета, книг, статей, — а сама предобученная модель (BERT, GPT и их многочисленные потомки) выступает готовой "базой знаний о языке": она уже знает грамматику, устойчивые словосочетания, базовые факты о мире, стиль и структуру типичных текстов, — точно так же как ранние слои ResNet50 уже "знают" грани и текстуры.
Ключевое отличие NLP-переноса от переноса в компьютерном зрении — способ предобучения. ImageNet-сети предобучаются с учителем (supervised): каждому изображению сопоставлен один из 1000 размеченных классов. Языковые модели вроде BERT и GPT предобучаются self-supervised способом — без единой ручной разметки, а лишь предсказывая скрытые или следующие слова прямо внутри самого текста: BERT учится восстанавливать случайно замаскированные слова в предложении (masked language modeling), а GPT учится предсказывать следующее слово по всем предыдущим (autoregressive modeling). Именно отсутствие необходимости в ручной разметке позволило предобучить эти модели на несопоставимо больших объёмах текста, чем можно было бы собрать для любой конкретной размеченной задачи, — и именно из этого масштаба выросла та самая "база знаний о языке", которую затем дообучают под конкретику.
Формальное определение
Transfer learning для языковых моделей. Языковая модель $f_\theta$ (BERT, GPT или родственная архитектура на основе трансформера, урок 343) предобучается self-supervised способом на огромном неразмеченном корпусе текста, решая вспомогательную задачу (masked language modeling для BERT, next-token prediction для GPT), не связанную напрямую ни с одной конкретной прикладной задачей. Результат предобучения — параметры $\theta$, кодирующие широкий спектр языковых закономерностей: синтаксис, семантику отдельных слов и словосочетаний, элементарные факты о мире, встретившиеся в обучающем корпусе. Для конкретной прикладной задачи (классификация тональности отзыва, извлечение именованных сущностей, ответ на вопрос по тексту) поверх $f_\theta$ добавляется небольшая новая "голова" под конкретную задачу, и вся конструкция дообучается (fine-tuning) на существенно меньшем размеченном датасете конкретной задачи — типично от нескольких сотен до нескольких десятков тысяч примеров, что на порядки меньше объёма корпуса, использованного для предобучения.
Разбор примеров
Пример 1 (fine-tuning BERT на классификации тональности отзывов). Задача — по тексту отзыва на товар определить, позитивный он или негативный, датасет — 3000 размеченных отзывов интернет-магазина. Обучение с нуля трансформерной архитектуры сопоставимого размера на таком количестве текста дало бы модель, немногим лучше случайного угадывания, — трансформерам (урок 343) для содержательного обучения языковым закономерностям нужны миллиарды слов, а не три тысячи отзывов. Вместо этого берём предобученный BERT и дообучаем:
from transformers import AutoTokenizer, AutoModelForSequenceClassification, Trainer, TrainingArguments
tokenizer = AutoTokenizer.from_pretrained("bert-base-multilingual-cased")
model = AutoModelForSequenceClassification.from_pretrained(
"bert-base-multilingual-cased", num_labels=2 # позитив / негатив
)
training_args = TrainingArguments(
output_dir="./results",
learning_rate=2e-5, # типичный маленький lr для fine-tuning BERT
num_train_epochs=3, # обычно 2-4 эпохи достаточно
per_device_train_batch_size=16,
)
trainer = Trainer(model=model, args=training_args, train_dataset=train_dataset)
trainer.train()
За несколько эпох на одной видеокарте модель достигает точности, недостижимой при обучении с нуля на тех же 3000 примерах, потому что BERT уже "знает" язык — ему остаётся лишь научиться сопоставлять уже понятый смысл текста с двумя конкретными метками.
Пример 2 (GPT как основа для генеративных задач). В отличие от BERT, который лучше подходит для задач понимания (классификация, поиск, извлечение сущностей — урок 344 разбирал это разделение подробно), GPT-подобные модели переносятся на генеративные задачи: дообученная на диалогах служба поддержки GPT-модель учится отвечать в стиле и терминологии конкретной компании, дообученная на юридических документах — генерировать черновики договоров в нужном стиле. Здесь перенос работает по тому же принципу — предобученная модель уже умеет строить грамматически правильные, связные предложения на нужном языке, и дообучение лишь смещает её "стиль и содержание" в сторону узкой предметной области, вместо того чтобы заново учить модель самому базовому владению языком.
Пример 3 (multilingual-перенос — перенос между языками). Особенно наглядный случай переноса в NLP — многоязычные модели вроде bert-base-multilingual-cased или современные многоязычные LLM: предобученные на смеси текстов на множестве языков одновременно, они выучивают представления слов и понятий, которые оказываются схожими для семантически близких слов на разных языках (эмбеддинг русского слова "собака" и английского "dog" располагаются близко друг к другу во внутреннем представлении модели, потому что модель видела оба слова в схожих контекстах). Это позволяет дообучить такую модель на размеченных данных для одного языка (скажем, английского, где размеченных датасетов исторически куда больше) и получить приемлемое качество на другом языке (русском) даже с минимальной дополнительной разметкой именно на этом языке — ещё одна форма переноса обучения, на этот раз не между задачами, а между языками внутри одной и той же модели.
Почему это важно
Перенос обучения в NLP через BERT и GPT — это прямое практическое применение всего материала этого блока курса о языковых моделях: аттеншн-механизм и архитектура трансформера (уроки 342–343) объясняют, как устроена сама модель, а перенос обучения объясняет, почему её вообще можно эффективно использовать для конкретной задачи, а не только изучать как абстрактную архитектуру. Ровно тот же паттерн мышления, что мы разобрали для изображений — предобученная универсальная модель плюс маленький размеченный датасет для дообучения, — сегодня лежит в основе подавляющего большинства реальных NLP-продуктов: чат-ботов, систем модерации контента, поисковых систем, инструментов автоматического реферирования текста. Понимание того, что фундаментально это тот же самый transfer learning, что и в компьютерном зрении, — не просто красивая аналогия, а практическое знание: те же самые вопросы (сколько у меня данных? насколько моя задача похожа на предобучение? какой шаг обучения выбрать для fine-tuning?) применимы что к ResNet50 на фотографиях родинок, что к BERT на отзывах покупателей.
Практика: 30 заданий
Базовые задания (1–10)
Задание 1: Объясни своими словами, в чём принципиальное отличие transfer learning от обучения модели с нуля.
Задание 2: Почему ранние слои сверточной сети переносятся между задачами лучше, чем поздние?
Задание 3: Чем feature extraction отличается от fine-tuning с точки зрения того, какие веса обновляются при обучении?
Задание 4: У тебя 500 фотографий для классификации 3 видов кактусов, задача похожа на ImageNet (там есть похожие классы растений). Какой подход разумнее — feature extraction или полный fine-tuning?
Задание 5: Напиши код PyTorch, который загружает предобученный ResNet50 и замораживает у него все веса.
Задание 6: Почему при fine-tuning используется существенно меньший шаг обучения, чем при обучении с нуля?
Задание 7: Что такое "голова" (head) и "тело" (backbone) предобученной сети в контексте transfer learning?
Задание 8: В чём разница между способом предобучения ImageNet-сетей (например, ResNet) и способом предобучения BERT?
Задание 9: У тебя есть предобученная модель для изображений (ResNet50) и задача предсказать цену квартиры по табличным данным (площадь, этаж, район). Подойдёт ли здесь прямой transfer learning с этой модели?
Задание 10: Перечисли, откуда можно скачать готовые предобученные модели для изображений и для текста.
Средние задания (11–20)
Задание 11 (практика): У тебя 60 000 фотографий для задачи, похожей на ImageNet (классификация повседневных бытовых предметов). Какую стратегию из практической матрицы стоит выбрать?
Задание 12: Напиши код, который замораживает все слои ResNet50, кроме последнего блока (layer4) и новой головы.
Задание 13 (практика): У тебя 400 аэрофотоснимков сельскохозяйственных полей — задача существенно отличается от ImageNet и по цветовой гамме, и по масштабу объектов. Данных мало. Какая стратегия разумна и почему это самый трудный случай матрицы?
Задание 14: Что такое дифференцированные шаги обучения (differential learning rates) при fine-tuning и зачем они нужны?
Задание 15: Объясни явление "катастрофического забывания" применительно к fine-tuning на маленьком датасете.
Задание 16 (практика): Напиши код на Hugging Face Transformers, который загружает предобученный BERT и подготавливает его для задачи бинарной классификации текста.
Задание 17: Почему нельзя обучить BERT-подобную модель с нуля на датасете из 3000 размеченных отзывов и рассчитывать на хорошее качество?
Задание 18: Какая из двух моделей — BERT или GPT — лучше подходит для задачи классификации email на спам, и почему?
Задание 19 (практика): Объясни, почему многоязычная модель (например, bert-base-multilingual-cased), дообученная на английских размеченных данных, может показывать приемлемое качество и на русском тексте той же задачи.
Задание 20: У тебя есть выбор между resnet50(pretrained=True) и resnet50(pretrained=False) для датасета всего в 200 изображений. Обоснуй, какой вариант выбрать.
Продвинутые задания (21–30)
Задание 21 (практика): Спроектируй стратегию transfer learning для задачи: классификация 4 стадий диабетической ретинопатии по снимкам глазного дна, датасет — 5000 размеченных снимков, домен визуально сильно отличается от ImageNet.
Задание 22: Почему первый свёрточный слой ResNet50, обученной на ImageNet, скорее всего останется полезным даже для гистологических изображений тканей, тогда как последний свёрточный блок — вряд ли?
Задание 23 (практика): Реализуй расписание обучения в два этапа: сначала feature extraction на 5 эпох, затем частичный fine-tuning на ещё 10 эпох с маленьким lr. Опиши шаги кода.
Задание 24: Почему важно "прогреть" (сначала обучить только голову) новую голову перед тем, как размораживать backbone, а не размораживать всё сразу с самого начала обучения?
Задание 25 (практика): Сравни ожидаемое время обучения feature extraction и полного fine-tuning на одном и том же датасете и объясни разницу.
Задание 26: В чём разница между transfer learning в компьютерном зрении, где предобучение supervised (ImageNet с разметкой), и в NLP, где предобучение self-supervised (BERT/GPT без разметки)?
Задание 27 (практика): Тебе нужно дообучить GPT-подобную модель на диалогах службы поддержки конкретной компании. Какой шаг обучения ты бы выбрал для fine-tuning и почему не стоит брать такой же lr, как при обучении с нуля?
Задание 28: Сравни transfer learning и обучение "с нуля" по трём критериям: требуемый объём данных, время обучения, итоговое качество при достаточном количестве данных для обучения с нуля.
Задание 29 (практика): Объясни, почему в задаче про перенос между визуальными доменами (пример 2 раздела про идею переноса — гистологические срезы) полная заморозка всей сети скорее всего даст худший результат, чем частичная разморозка последних блоков.
Задание 30 (практика): Опиши end-to-end пайплайн transfer learning для собственного пет-проекта: классификация 10 видов уличной еды по фотографии, датасет — 1200 изображений, собранных вручную из интернета.
Частые ошибки
Ошибка 1. Замораживают весь backbone и обучают только голову, даже когда датасет большой и домен сильно отличается от ImageNet.
Как выглядит: точность модели упирается в невысокий потолок и не растёт, сколько бы эпох ни обучали новую голову, хотя данных достаточно для более глубокой адаптации.
Почему возникает: feature extraction — самый простой и быстрый вариант кода, и его выбирают по умолчанию, не сверяясь с практической матрицей "размер датасета × похожесть задачи".
Как правильно: при большом датасете и непохожем домене стоит переходить к fine-tuning — размораживать хотя бы последние блоки сети, позволяя специфичным признакам адаптироваться под новый домен.
Ошибка 2. Используют такой же большой шаг обучения при fine-tuning, как при обучении с нуля.
Как выглядит: точность модели после нескольких эпох fine-tuning не улучшается, а падает — модель "теряет" то качество, которое было сразу после загрузки предобученных весов.
Почему возникает: значение шага обучения копируют из туториала по обучению сети с нуля, не задумываясь о том, что предобученные веса уже находятся в удачной точке и требуют куда более осторожного обновления.
Как правильно: для fine-tuning использовать шаг обучения в 10-100 раз меньше, чем при обучении с нуля — обычно в диапазоне $10^{-5}$–$10^{-4}$ для сверточных сетей и $10^{-5}$–$2\times10^{-5}$ для BERT-подобных моделей.
Ошибка 3. Полностью размораживают всю сеть и дообучают её целиком на датасете из нескольких сотен примеров.
Как выглядит: модель показывает отличную точность на обучающей выборке, но заметно хуже на валидации — классический признак переобучения.
Почему возникает: ошибочное предположение "чем больше параметров можно обучать, тем лучше результат", без учёта соотношения числа обучаемых параметров и объёма доступных данных.
Как правильно: на маленьком датасете предпочитать feature extraction или заморозку большей части сети — число обучаемых параметров должно быть соразмерно объёму данных, а не максимально возможным.
Ошибка 4. Пытаются напрямую перенести сеть, обученную на изображениях, на данные принципиально другого типа — например, на табличные данные или временные ряды.
Как выглядит: попытка "скормить" табличные признаки предобученной ResNet50 в надежде, что перенос сработает так же, как для изображений.
Почему возникает: недооценка того, что перенос требует совпадения структуры входных данных, а не просто общей "похожести задач" на словах.
Как правильно: transfer learning работает между задачами одного типа данных (изображение → изображение, текст → текст); для табличных данных стоит опираться на классические модели (уроки 310–318) или конструирование признаков (урок 325), а не на визуальные архитектуры.
Ошибка 5. Забывают, что предобученные модели ожидают вход в определённом формате (нормализация, размер изображения), и подают на вход сырые данные без предобработки.
Как выглядит: модель после загрузки предобученных весов выдаёт заметно худшее качество, чем ожидается, ещё до всякого дообучения.
Почему возникает: предобученные сети обучались на данных, нормализованных определённым образом (для ImageNet-моделей — вычитание среднего и деление на стандартное отклонение по конкретным числам RGB-каналов, изображение приведено к конкретному размеру), и без этой же предобработки на входе распределение данных не соответствует тому, на чём сеть обучалась.
Как правильно: всегда использовать те же преобразования предобработки (resize, нормализация конкретными числами), что были применены при исходном предобучении конкретной модели — они обычно документированы вместе с весами (например, в torchvision.models — через объект weights.transforms()).
Ошибка 6. Считают fine-tuning всегда строго лучше feature extraction и применяют его по умолчанию независимо от размера датасета.
Как выглядит: на датасете в несколько сотен примеров сразу размораживают всю сеть "для лучшего качества" и получают результат хуже, чем дал бы простой feature extraction.
Почему возникает: интуитивное (но неверное) убеждение, что больше степеней свободы в обучении всегда означает лучший результат, без учёта риска переобучения на малом датасете.
Как правильно: выбор между feature extraction и fine-tuning — не вопрос "что лучше в принципе", а вопрос конкретного соотношения размера датасета и похожести задачи, разобранного в практической матрице выше.
Главное запомнить
-
Transfer learning — использование модели, уже обученной на большом стороннем датасете (например, ImageNet для изображений или огромный корпус текста для языковых моделей), в качестве стартовой точки для своей, как правило, значительно меньшей задачи, вместо обучения с нуля.
-
Перенос работает благодаря иерархии признаков (уроки 326, 335): ранние слои сети выучивают универсальные, предметно-независимые признаки — грани, текстуры, простые формы, — которые полезны практически для любой задачи компьютерного зрения, а не только той, на которой сеть обучалась изначально.
-
Feature extraction — замораживаешь все веса предобученной сети, обучаешь только новый последний слой под свою задачу; быстрый и экономный подход, лучше всего работающий на маленьком датасете и похожей на исходную задаче.
-
Fine-tuning — размораживаешь часть или все веса предобученной сети и дообучаешь всю сеть на своих данных с существенно уменьшенным шагом обучения (обычно в 10-100 раз меньше, чем при обучении с нуля); требует больше данных, но даёт лучшую адаптацию к специфике задачи.
-
Выбор между подходами определяется практической матрицей: размер своего датасета (маленький / большой) и похожесть своей задачи на исходную задачу предобучения (похожая / непохожая) — маленький датасет и похожая задача сильнее всего тяготеют к feature extraction, большой датасет и непохожая задача — к полному fine-tuning.
-
Частичная заморозка (заморозить ранние универсальные слои, разморозить и дообучить поздние специфичные) — самый распространённый на практике компромисс между двумя крайностями.
-
В NLP та же идея реализована через предобученные языковые модели (BERT, GPT, урок 344): они предобучаются self-supervised способом на огромном неразмеченном корпусе текста и служат готовой "базой знаний о языке", которую дообучают под конкретную задачу на существенно меньшем размеченном датасете.
-
Transfer learning работает только между задачами с одинаковым типом и структурой входных данных — изображение переносится на изображение, текст переносится на текст, но не на данные принципиально другой природы (например, табличные).
-
Pretrained model zoo — готовые предобученные модели, доступные для скачивания:
torchvision.modelsиkeras.applicationsдля изображений (ResNet, EfficientNet, Inception и другие ImageNet-модели), Hugging Face Model Hub для NLP-моделей (BERT, GPT и их варианты). -
Transfer learning — не "продвинутая опциональная техника", а стандартная отправная точка подавляющего большинства успешных практических проектов Deep Learning: обучение с нуля сегодня скорее исключение, оправданное лишь очень специфичным доменом данных или ролью исследователя архитектур.
Связь с темами курса
Что нужно было знать до этого урока
Этот урок напрямую опирается на понятие иерархии признаков, впервые введённое в уроке 326 про искусственные нейронные сети и наглядно продемонстрированное на конкретных фильтрах свёрточных сетей в уроке 335: там было показано, что ранние слои сети реагируют на простые локальные паттерны (грани, текстуры), а поздние — на всё более сложные и абстрактные признаки (части объектов, целые объекты). Transfer learning — это прямое практическое следствие этой закономерности: именно потому, что ранние признаки универсальны, а не специфичны для конкретной задачи, их можно переиспользовать в другой задаче без переобучения. Из блока про конкретные CNN-архитектуры (уроки 336-338) взяты конкретные модели, которые чаще всего используются как основа для переноса — ResNet (урок 337) с его skip-connections, Inception и EfficientNet (урок 338). Из блока оптимизации (уроки 285, 293) взято понятие шага обучения и его роли в градиентном спуске — центральное для понимания, почему fine-tuning требует именно маленького шага обучения. А из урока 344 про BERT, GPT и языковые модели взято понимание архитектуры трансформера и двух парадигм предобучения (masked language modeling и autoregressive modeling), которые сегодня оказались частным случаем той же самой общей идеи переноса обучения, что и перенос между CNN-задачами.
Что изучить дальше
Следующий урок блока (349) разбирает meta-learning ("обучение обучению") — идею, логически продолжающую transfer learning на следующий уровень: вместо того чтобы переносить одну конкретную предобученную модель на одну конкретную новую задачу, meta-learning ставит целью обучить модель так, чтобы она умела быстро адаптироваться к любой новой, ранее не встречавшейся задаче буквально по нескольким примерам (few-shot learning) — идейное развитие того же самого вопроса "как использовать уже накопленные знания для быстрой адаптации", который был центральным сегодня. Понимание feature extraction и fine-tuning, разобранное в этом уроке, станет прямым фундаментом для того, чтобы увидеть, чем принципиально meta-learning отличается от "обычного" переноса обучения.
Где это нужно в жизни
🏥 Медицинская диагностика. Классификация рентгеновских снимков, МРТ, гистологических срезов и снимков глазного дна почти всегда строится через fine-tuning ImageNet-предобученных сетей — медицинских размеченных датасетов редко бывает достаточно для обучения с нуля, а transfer learning позволяет достигать клинически применимого качества на датасетах в тысячи, а не миллионы примеров.
🏭 Промышленный контроль качества. Обнаружение дефектов на производственной линии (трещины на деталях, брак на печатных платах, дефекты сварных швов) — классический сценарий transfer learning: собрать миллион фотографий брака нереально, а дообучить предобученную сеть на паре тысяч примеров — стандартная и работающая практика.
💬 Продукты на основе языковых моделей. Чат-боты службы поддержки, системы модерации контента, классификаторы тональности отзывов, инструменты автоматического реферирования — практически все они строятся через fine-tuning предобученных BERT- или GPT-подобных моделей (урок 344) на относительно небольшом размеченном датасете конкретной компании или продукта.
📱 Мобильные и embedded-приложения. Приложения для распознавания растений, продуктов питания, пород животных по фотографии со смартфона типично используют компактные предобученные модели (MobileNet, EfficientNet-lite), дообученные под узкий набор классов конкретного приложения — без transfer learning разработка подобного приложения силами небольшой команды была бы практически невозможна.
🔬 Научные и нишевые домены с ограниченными данными. Классификация спутниковых снимков, идентификация видов по фотографиям в полевой биологии, анализ произведений искусства — во всех этих областях, где сбор и разметка данных особенно дороги и медленны, transfer learning остаётся практически единственным реалистичным способом получить рабочую модель в разумные сроки.
Интересные факты
-
Работа Йосинского, Клуна, Бенджио и Липсона 2014 года "How transferable are features in deep neural networks?" количественно показала: даже когда исходная и целевая задачи ImageNet искусственно составлялись из совершенно непересекающихся наборов классов, перенос первых нескольких слоёв всё равно давал заметный прирост качества по сравнению со случайной инициализацией — прямое экспериментальное подтверждение того, что самые ранние признаки универсальны почти независимо от конкретного содержания задачи.
-
Датасет ImageNet, на котором предобучено абсолютное большинство доступных сегодня "из коробки" моделей компьютерного зрения, содержит около 1,2 миллиона размеченных изображений и 1000 классов — но общий объём данных, потраченных на разметку полной версии ImageNet (более 14 миллионов изображений, свыше 20 000 категорий), потребовал труда тысяч людей через краудсорсинговую платформу Amazon Mechanical Turk на протяжении нескольких лет; переиспользуя веса, обученные на этих данных, ты фактически бесплатно получаешь результат многолетней коллективной работы.
-
Hugging Face Model Hub, ставший стандартным местом для скачивания предобученных NLP-моделей, на момент написания этого урока насчитывает сотни тысяч выложенных моделей — от базовых версий BERT и GPT до узкоспециализированных моделей, дообученных сообществом под конкретные языки, домены и задачи, что само по себе является ещё одним слоем переноса: дообученную кем-то модель можно взять и дообучить ещё раз под свою, ещё более узкую задачу.
-
Явление "катастрофического забывания" при агрессивном fine-tuning на маленьких датасетах — не специфика нейросетей: похожая проблема (резкое ухудшение ранее усвоенного при обучении новому) изучается и в психологии обучения человека, что стало одним из источников вдохновения для методов постепенного, "бережного" обучения в области continual learning, тесно смежной с темами transfer learning и meta-learning.
Лайфхаки
-
Всегда начинай с самой простой стратегии — feature extraction на замороженной сети — прежде чем переходить к fine-tuning; это займёт минуты, даст быстрый бейзлайн и покажет, стоит ли вообще инвестировать время в более сложную и рискованную разморозку весов.
-
Для шага обучения при fine-tuning сверточных сетей отталкивайся от диапазона $10^{-5}$–$10^{-4}$, а для BERT-подобных моделей — от $10^{-5}$–$2\times10^{-5}$; если после первой эпохи fine-tuning точность на валидации резко падает, это почти всегда сигнал, что шаг обучения завышен, а не что подход выбран неверно.
-
Используй дифференцированные шаги обучения (differential learning rates) — меньший lr для backbone, больший для новой головы — вместо единого значения на всю сеть: это позволяет новой, случайно инициализированной голове обучаться быстрее, не рискуя резкими шагами испортить уже полезные предобученные веса тела сети.
-
Перед размораживанием backbone обязательно "прогрей" новую голову несколько эпох в режиме чистого feature extraction — это снижает шум градиентов, доходящих до предобученных весов на самых нестабильных первых шагах обучения.
-
Никогда не забывай применить к входным данным ту же предобработку (нормализацию, размер изображения), которую использовали авторы предобученной модели — несоответствие форматов входа часто маскируется под "модель плохо переносится", хотя на деле проблема в элементарном рассогласовании предобработки.
-
Если качество после fine-tuning неожиданно ухудшилось по сравнению с чистым feature extraction, в первую очередь проверь три вещи по порядку: не завышен ли шаг обучения, не переобучилась ли сеть на маленьком датасете (сравни точность на обучающей и валидационной выборках) и не забыл ли ты добавить регуляризацию или раннюю остановку (уроки 331-333) при разморозке большего числа весов.
-
Держи под рукой практическую матрицу "размер датасета × похожесть задачи" как чек-лист перед стартом любого нового проекта transfer learning — она экономит недели впустую потраченных на угадывание экспериментов.
Пожалуй, из всего блока Deep Learning этого курса сегодняшняя техника — самая быстро окупаемая в реальной работе: за один вечер, вооружившись одной строчкой pretrained=True и пониманием того, когда замораживать веса, а когда осторожно их дообучать, ты способен получить рабочую модель там, где обучение с нуля потребовало бы данных и вычислений, недоступных подавляющему большинству команд. Именно поэтому transfer learning — не факультативная деталь курса, а один из тех навыков, которые отличают специалиста, способного довести проект до продакшена в разумные сроки, от того, кто застревает, пытаясь повторить путь исследователей ImageNet с нуля. Следующий урок покажет, как эту же идею можно довести до предела — научить модель адаптироваться не просто к одной новой задаче, а буквально к любой новой задаче за считаные примеры.
Понял тему? Закрепи в боте! 🚀
Попрактикуйся на задачах и получи персональные рекомендации от AI
💪 Начать тренировку