Вручную спроектированные архитектуры — результат опыта и интуиции, но их перебор ограничен. Мы в TrueTech используем NAS (Neural Architecture Search) — алгоритмический поиск архитектурного пространства с оптимизацией под конкретную задачу, датасет и hardware target. Это не замена архитектурному мышлению, а способ найти конфигурации, до которых человек не дойдёт за разумное время. Используем методы DARTS, Once-for-All и predictor-based подхода — каждый для своих условий. Хотите проверить, принесёт ли NAS пользу вашему проекту? Свяжитесь — сделаем предварительную оценку за пару дней.
Почему наивный NAS убивает GPU-бюджет
Классический NAS в ранних реализациях (например, NASNet от Google) требовал до 500 GPU-дней на A100-эквиваленте. Каждая кандидатная архитектура обучалась с нуля до сходимости. При пространстве поиска в 10^10 конфигураций полный перебор невозможен. Современные подходы решают это через три принципиально разные идеи:
- One-shot NAS / Weight Sharing. Суперсеть включает все возможные подграфы, каждый кандидат — «путь» через неё с уже обученными весами. DARTS, SNAS, Single-Path NAS — время поиска падает с сотен GPU-дней до 1-4 дней (ускорение в 100 раз).
- Predictor-based NAS. Суррогатная модель предсказывает accuracy без полного обучения. 100-200 реальных оценок → предиктор для следующих миллионов кандидатов.
- Hardware-aware NAS. Оптимизация по accuracy и latency на конкретном устройстве. MNasNet, FBNet, Once-for-All строят Pareto-фронт (accuracy vs latency). Критично для edge deployment.
Как DARTS решает проблему скорости?
DARTS (Differentiable Architecture Search) — один из самых используемых one-shot методов. Вместо дискретного выбора операции (3×3 conv vs 5×5 conv vs skip) используются непрерывные веса α, оптимизируемые через gradient descent. Подробное описание — в оригинальной статье Liu et al., DARTS: Differentiable Architecture Search, arXiv:1806.09055.
import torch
import torch.nn as nn
from torch.nn import functional as F
class MixedOp(nn.Module):
def __init__(self, C: int, stride: int):
super().__init__()
self._ops = nn.ModuleList()
for primitive in PRIMITIVES:
op = OPS[primitive](C, stride, affine=False)
self._ops.append(op)
def forward(self, x: torch.Tensor, weights: torch.Tensor) -> torch.Tensor:
return sum(w * op(x) for w, op in zip(weights, self._ops))
class DARTSCell(nn.Module):
def __init__(self, steps, multiplier, C_prev_prev, C_prev, C, reduction, reduction_prev):
super().__init__()
self._steps = steps
self._multiplier = multiplier
def forward(self, s0, s1, weights):
states = [s0, s1]
offset = 0
for i in range(self._steps):
s = sum(self._ops[offset + j](h, weights[offset + j]) for j, h in enumerate(states))
offset += len(states)
states.append(s)
return torch.cat(states[-self._multiplier:], dim=1)
def train_darts_step(model, architect, optimizer_w, optimizer_alpha, train_queue, valid_queue, lr_w):
for step, (input_train, target_train) in enumerate(train_queue):
input_valid, target_valid = next(iter(valid_queue))
architect.step(input_train, target_train, input_valid, target_valid, lr=lr_w, optimizer=optimizer_w, unrolled=False)
optimizer_w.zero_grad()
logits = model(input_train)
loss = F.cross_entropy(logits, target_train)
loss.backward()
nn.utils.clip_grad_norm_(model.parameters(), max_norm=5.0)
optimizer_w.step()
Главная инженерная сложность — двухуровневая оптимизация: веса сети w и архитектурные веса α чередуются. Однако в чистом DARTS возникает коллапс операций: skip-connection «побеждают» из-за нулевых параметров. Решения — DARTS+ (отсечение skip), P-DARTS (прогрессивная глубина), GDAS (Gumbel-softmax).
Что даёт hardware-aware NAS на практике?
Пошаговый запуск OFA для мобильного деплоя
- Загрузите предобученную суперсеть
ofa_mbv3_d234_e346_k357_w1.0. - Измерьте latency всех операций на целевом устройстве (например, Note10).
- Создайте предиктор эффективности на основе замеров.
- Запустите эволюционный поиск с ограничением latency (25ms) — 500 итераций.
- Извлеките лучшую подсеть и экспортируйте в ONNX.
Once-for-All (MIT) — суперсеть, из которой без дообучения извлекаются подсети под любой hardware constraint:
from ofa.model_zoo import ofa_net
o fa_network = ofa_net('ofa_mbv3_d234_e346_k357_w1.0', pretrained=True)
from ofa.nas.efficiency_predictor import Latency_MBV3_MeasuredNet
efficiency_predictor = Latency_MBV3_MeasuredNet('note10', ofa_network)
from ofa.nas.search_algorithm.evolution_finder import EvolutionFinder
finder = EvolutionFinder(efficiency_constraint=25, efficiency_predictor=efficiency_predictor, accuracy_predictor=accuracy_predictor, population_size=100, max_time_budget=500)
best_valids, best_info = finder.run_evolution_search()
В реальном проекте: NAS под MobileNetV3-space для классификации производственного брака (640×480, 12 классов) на NVIDIA Jetson Nano. Ручная MobileNetV3-Large: 28.4ms, accuracy 91.3%. OFA-поиск за 6 часов: 22.1ms, accuracy 92.7% — без единого ручного изменения. При этом DARTS быстрее эволюционного поиска в 100 раз, но даёт менее точные предсказания latency на нестандартном железе.
| Метод | Время поиска (GPU-дни) | Точность (acc) | Уровень автоматизации | Подходит для edge |
|---|---|---|---|---|
| Evolutionary NAS | 300-500 | Высокая | Низкий | Нет |
| DARTS (one-shot) | 1-4 | Высокая | Средний | Ограниченно |
| Predictor-based | 1-3 | Средняя | Высокий | Да |
| Hardware-aware (OFA) | 0.25-1 | Высокая | Высокий | Да |
Что входит в работу над NAS?
| Этап | Действия | Артефакты |
|---|---|---|
| Определение search space | Задание блоков, операций, диапазонов каналов | JSON-конфиг search space |
| Выбор стратегии | DARTS / evolutionary / predictor-based | План эксперимента |
| Профилирование железа | Замер latency всех операций на production hardware | CSV с профилями |
| Поиск кандидатов | Запуск поиска, трекинг в W&B (MLOps) | Найденные архитектуры |
| Полное обучение | Обучение финальной архитектуры с нуля | Веса модели, чекпоинты |
| Валидация | Holdout set, тест на целевом железе | Отчёт с метриками |
Когда NAS оправдан?
NAS не нужен для стандартных задач с данными < 50k примеров — возьмите предобученную ResNet-50. Он оправдан при:
- кастомных hardware-ограничениях (Jetson, Coral, ASIC),
- нетипичных входных данных (гиперспектр, лидары, медицинские снимки),
- необходимости кардинально уменьшить модель без потери качества.
Мы специализируемся на оптимизации нейросетей более 5 лет, реализовали 15+ проектов с автоматическим поиском архитектуры. Получите консультацию — оценим, какие методы NAS сработают для вашей задачи.







