中文翻译暂不可用,显示俄语原文。
Реализовать curriculum learning
ТЕХНИЧЕСКОЕ ЗАДАНИЕ: Реализовать curriculum learning
1. Цель задачи
Разработать и протестировать стратегию curriculum learning — обучение модели на данных, отсортированных по возрастанию сложности (от простого к сложному). Цель — ускорить сходимость нейросети минимум на 30% по сравнению со стандартным случайным порядком подачи данных при сохранении финального качества.
Ключевой результат конвергенция (достижение целевой метрики, например 90% accuracy на валидации) происходит не менее чем на 30% быстрее по числу эпох.
2. Исходные данные
| Что нужно | Откуда взять |
|---|---|
| Датасет изображений (MNIST или CIFAR-10) | torchvision.datasets – загрузить через datasets.MNIST / datasets.CIFAR10 |
| Базовая модель (простая CNN) | Написать самостоятельно (пример кода ниже) |
| Метрика сложности примера | Реализовать один из вариантов: длина градиента, уверенность предобученного оракула, размер объекта (для MNIST) |
| Стратегия curriculum | Разработать: разделить обучающую выборку на K уровней, подавать их в порядке возрастания, постепенно добавляя новые уровни |
Если нет реального инструмента — симулируем:
- Используем встроенные датасеты PyTorch (MNIST доступен всегда).
- В качестве метрики сложности для простоты берём среднюю интенсивность пикселей (чем меньше чёрных пикселей, тем пример сложнее) — для MNIST это разумно.
- Реализацию curriculum делаем через кастомный DataLoader / Dataset, который на каждой эпохе выдает batch из первых
tуровней, гдеtрастёт от 1 до K.
3. Технологический стек
| Компонент | Инструменты | Назначение |
|---|---|---|
| Язык программирования | Python 3.10+ | Основной язык |
| Фреймворк глубокого обучения | PyTorch 2.x | Построение и обучение модели |
| Работа с данными | torchvision, numpy | Загрузка и предобработка датасетов, сортировка |
| Визуализация | matplotlib, seaborn | Графики сходимости, loss/accuracy |
| Эксперименты | Jupyter Notebook / Python script | Воспроизводимость |
| Управление зависимостями | requirements.txt | Фиксация версий |
4. Этапы выполнения
Этап 1: Подготовка данных и определение метрики сложности (≈1 час)
Действия
- Загрузить датасет MNIST (или CIFAR-10) через torchvision.datasets. Разделить на train/val (50000/10000 для CIFAR-10; для MNIST 60000/10000).
- Реализовать метрику сложности для каждого обучающего примера:
- Для MNIST: средняя яркость пикселя (нормализованная от 0 до 1). Чем меньше яркость (тёмные изображения), тем "сложнее" — т.к. цифра меньше контрастирует.
- Альтернативно: длина градиента после одного прохода через маленькую обученную модель-оракул (но это требует дополнительного обучения, поэтому для простоты берём яркость).
- Создать функцию compute_difficulty(dataset), возвращающую массив вещественных значений сложности для каждого образца.
- Отсортировать индексы обучающей выборки по возрастанию сложности (от самых простых к самым сложным).
- Разделить отсортированные данные на K=5 равных (или по количеству) уровней (buckets) — каждый уровень содержит ровно
len(train)/Kпримеров.
import torchvision
import numpy as np
def compute_difficulty(dataset):
difficulties = []
for img, label in dataset:
# img: Tensor [1,28,28] для MNIST
difficulties.append(img.mean().item()) # средняя яркость
return np.array(difficulties)
full_train = torchvision.datasets.MNIST(root='./data', train=True, download=True)
difficulties = compute_difficulty(full_train)
sorted_indices = np.argsort(difficulties) # от меньшей яркости (просто) к большей (сложно)
Ожидаемый результат этапа
- Отсортированный список индексов обучающей выборки по возрастанию сложности.
- Создан массив
sorted_indicesи разбивка на 5 уровней (например,level_indices = np.array_split(sorted_indices, 5)).
Этап 2: Создание стратегии curriculum (≈1 час)
Действия
- Реализовать класс
CurriculumDataset, наследующий torch.utils.data.Dataset.- На вход принимает исходный датасет, список уровней (каждый уровень — список индексов), текущий номер эпохи (
current_epoch) и максимальное количество эпох (max_epochs). - Метод
__len__возвращает сумму длин уровней от 0 доcurrent_level, гдеcurrent_level = min( int(current_epoch / max_epochs * K), K-1 ). - Метод
__getitem__возвращает пример из одного из активных уровней (равномерно или пропорционально).
- На вход принимает исходный датасет, список уровней (каждый уровень — список индексов), текущий номер эпохи (
- Реализовать функцию get_curriculum_loader(epoch, ...), которая создаёт DataLoader с правильным
CurriculumDataset. - Подготовить baseline: обычный DataLoader с полным перемешиванием (shuffle=True).
- Убедиться, что на первой эпохе в curriculum попадают только самые простые примеры (уровень 0), на последней — все уровни.
class CurriculumDataset(Dataset):
def __init__(self, base_dataset, level_indices, current_epoch, max_epochs, K=5):
self.base = base_dataset
self.levels = level_indices
self.current_level = min(int(current_epoch / max_epochs * K), K-1)
# объединяем индексы всех уровней до current_level
self.active_indices = []
for i in range(self.current_level + 1):
self.active_indices.extend(self.levels[i])
def __len__(self): return len(self.active_indices)
def __getitem__(self, idx):
real_idx = self.active_indices[idx]
return self.base[real_idx]
Ожидаемый результат этапа
- Реализованы классы и функции для генерации батчей как в режиме curriculum, так и baseline.
- Проверено, что на первой эпохе используется только уровень 0, на последней — все 5.
Этап 3: Базовая модель и обучение (≈1.5 часа)
Действия
- Определить простую свёрточную сеть:
class SimpleCNN(nn.Module):
def __init__(self, num_classes=10):
super().__init__()
self.conv1 = nn.Conv2d(1, 32, 3, padding=1)
self.conv2 = nn.Conv2d(32, 64, 3, padding=1)
self.pool = nn.MaxPool2d(2,2)
self.fc1 = nn.Linear(64*7*7, 128)
self.fc2 = nn.Linear(128, num_classes)
def forward(self, x):
x = self.pool(torch.relu(self.conv1(x)))
x = self.pool(torch.relu(self.conv2(x)))
x = x.view(x.size(0), -1)
x = torch.relu(self.fc1(x))
return self.fc2(x)
-
Зафиксировать гиперпараметры:
- Оптимизатор: Adam, lr=1e-3
- Batch size: 64
- Число эпох: 20 (или до достижения accuracy 90% на валидации)
- Функция потерь: CrossEntropyLoss
-
Обучить baseline (случайный shuffle) и сохранить лоссы/accuracy на валидации каждую эпоху.
-
Обучить модель с curriculum (используя
CurriculumDatasetс изменяющимся уровнем сложности). Важно: количество примеров в эпоху меняется, поэтому необходимо нормализовать метрики (можно фиксировать количество итераций, а не эпох, но для простоты считаем эпохи как проход по одному полному набору всех данных). Для корректного сравнения: в curriculum на ранних эпохах модель видит меньше данных, но зато они более информативны. Сравнивать будем по числу эпох (каждая эпоха содержит все примеры, но в curriculum – только активные уровни). Лучше проводить обучение до полной сходимости, измеряя число итераций.
Рекомендация Сделайте равное количество градиентных шагов. Задайте общее количество шагов (например, 5000). Для baseline — 5000 шагов на всех данных (shuffle). Для curriculum — те же 5000 шагов, но на первых шагах используются только простые примеры, а затем постепенно добавляются сложные.
Ожидаемый результат этапа
- Два файла с логами обучения (loss на train, accuracy на val) для baseline и curriculum.
- Код обучения в виде функций
train_baseline()иtrain_curriculum().
Этап 4: Анализ сходимости (≈1 час)
Действия
- Построить на одном графике validation accuracy по числу шагов/эпох для обеих стратегий.
- Определить порог accuracy (например, 90%). Найти номер шага (или эпохи), когда этот порог был впервые достигнут каждой стратегией.
- Вычислить относительное ускорение:
speedup = (steps_baseline - steps_curriculum) / steps_baseline * 100% - Если ускорение ≥ 30% — задача выполнена. Если нет — проанализировать причины (метрика сложности, количество уровней, гиперпараметры) и при необходимости скорректировать.
import matplotlib.pyplot as plt
steps = range(len(baseline_acc))
plt.plot(steps, baseline_acc, label='baseline')
plt.plot(steps, curriculum_acc, label='curriculum')
plt.axhline(90, color='gray', linestyle='--')
plt.legend()
plt.show()
Ожидаемый результат этапа
- График сходимости (png/pdf).
- Численное значение ускорения.
- Вывод о достижении цели.
Этап 5: Документирование и отчет (≈0.5 часа)
Действия
- Оформить код в виде Python-скрипта (или ноутбука) с комментариями.
- Написать краткий отчет (README или раздел в ноутбуке), содержащий:
- описание метрики сложности;
- параметры curriculum (K, закон роста);
- полученные графики;
- значение ускорения;
- анализ: почему curriculum помог (или не помог).
- Зафиксировать зависимости в requirements.txt (torch, torchvision, matplotlib, numpy).
Ожидаемый результат этапа
- Архив с кодом, результатами, графиками и отчетом.
- Четкое заключение о применимости curriculum learning для данного датасета.
5. Критерии приемки (Definition of Done)
- Определена и реализована воспроизводимая метрика сложности для датасета.
- Данные отсортированы по возрастанию сложности и разбиты на уровни.
- Реализована стратегия curriculum с динамическим расширением набора данных по мере обучения.
- Baseline (случайный порядок) и curriculum обучены на одинаковом количестве градиентных шагов с одними гиперпараметрами.
- Получены графики сходимости (loss/accuracy vs steps) для обеих стратегий.
- Ускорение конвергенции (по достижении порога accuracy) составляет не менее 30%.
- Код задокументирован, содержит README и может быть повторно запущен.
- В отчете объяснены причины ускорения или его отсутствия.
6. Ожидаемый результат
Основной результат — папка с файлами:
curriculum_learning.py— основной скрипт (илиcurriculum_learning.ipynb).requirements.txt— список зависимостей.results/— папка с логами обучения (baseline_log.npy,curriculum_log.npy).plots/convergence.png— график сходимости.README.md— отчет с выводами и инструкцией по запуску.
Дополнительно (опционально): анализ чувствительности к количеству уровней K, выбору метрики сложности, закону роста (линейный, логарифмический).
7. Возможные сложности и их решение
| Сложность | Решение |
|---|---|
| Метрика сложности (средняя яркость) может не коррелировать с реальной сложностью для модели. | Использовать альтернативную метрику: длина градиента после одного шага на небольшой предобученной сети (оракул). Реализовать как отдельную утилиту. |
| Количество данных в эпоху различается между baseline и curriculum, что усложняет сравнение по эпохам. | Сравнивать по количеству градиентных шагов (итераций). Для этого задать общее число шагов, а curriculum подаёт батчи из активного пула. |
| Переобучение на простых примерах на ранних этапах. | Добавить регуляризацию (dropout, weight decay) или медленнее увеличивать сложность (например, добавлять новый уровень не каждую эпоху, а через определённое число шагов). |
| Выбор количества уровней K. | Провести эксперимент с K=3,5,10. В отчёте указать, какое K дало наилучшее ускорение. |
| Воспроизводимость результатов. | Зафиксировать seed для PyTorch и NumPy, указать в коде. |
8. Бюджет времени (оценка)
| Этап | Время |
|---|---|
| Этап 1: Подготовка данных и метрика сложности | 1 час |
| Этап 2: Создание стратегии curriculum | 1 час |
| Этап 3: Базовая модель и обучение | 1.5 часа |
| Этап 4: Анализ сходимости | 1 час |
| Этап 5: Документирование и отчет | 0.5 часа |
| Итого | 5 часов |
Примечание: Для первого выполнения задачи может потребоваться до 7 часов, если возникнут сложности с выбором метрики или настройкой curriculum.
9. Связанные вопросы из базы знаний
| Вопрос | Тема |
|---|---|
| 12 | Data Augmentation: методы и реализация |
| 45 | Transfer Learning: тонкая настройка предобученных моделей |
| 128 | Learning Rate Scheduling: ReduceLROnPlateau, CosineAnnealing |
| 201 | Curriculum Learning: теоретические основы |
| 273 | Практика: Curriculum Learning (данное ТЗ) |
| 350 | Функции потерь: CrossEntropy, Focal Loss |
| 512 | Оценка модели: accuracy, precision, recall |
| 650 | Трюки обучения: Gradient Clipping, Batch Normalization |
| 789 | Batch Normalization: влияние на сходимость |
| 890 | Градиентный спуск: Adam, SGD, Momentum |
10. Чек-лист самопроверки
- Я выбрал датасет и реализовал метрику сложности (средняя яркость или альтернативу).
- Я отсортировал обучающую выборку и разбил её на уровни.
- Я создал класс
CurriculumDataset, который на каждой эпохе использует только часть уровней. - Я обучил baseline (shuffle) и curriculum при одинаковых гиперпараметрах и одинаковом количестве градиентных шагов.
- Я построил график сходимости и убедился, что ускорение составляет ≥30% (или объяснил, почему не получилось).
- Я задокументировал код, оформил результаты и написал отчет.