Оптимізація ML-моделі (pruning) для мобільного пристрою
Ми часто стикаємося з ситуацією, коли готова модель не влізає в пам'ять смартфона або працює занадто повільно. Pruning — один з ключових методів у нашому арсеналі для вирішення цієї проблеми. Це не просто видалення зайвих ваг, а тонкий процес, що вимагає розуміння архітектури та цільового пристрою. Нижче розберемо, як ми проводимо pruning під ключ, які результати гарантуємо і чому structured pruning — вибір №1 для мобільних додатків. Якщо ваша модель не вкладається в обмеження пристрою — зв'яжіться з нами, ми допоможемо.
Pruning — видалення частини ваг або нейронів з моделі. Логіка: в нейромережі, навченій на реальних даних, значна частка ваг близька до нуля і майже не впливає на вихід. Їх можна обнулити або видалити без істотної втрати точності, але з виграшем у швидкості та об'ємі.
Звучить привабливо. На практиці — pruning складніший за квантизацію, вимагає донавчання після проріджування і не завжди дає очікуване прискорення на мобільних пристроях через особливості реалізації. Наш багаторічний досвід показує, що універсального рецепту немає. Тому ми підходимо до задачі системно: спочатку аналізуємо модель, потім обираємо оптимальну стратегію.
Який pruning обрати для мобільного додатку?
Unstructured pruning — обнуляємо окремі ваги (sparse матриці). Матриця 90% нулів — здавалося б, 10× економія. Але GPU/NPU працюють з щільними матрицями, sparse обчислення там не прискорюються. Практична користь: зменшення розміру моделі після стиснення (нулі добре компресуються). Але не швидкість інференсу на звичайних пристроях.
Structured pruning — видаляємо цілі фільтри (канали) в згорткових шарах або голови в attention. Результат — фізично менший граф, який реально швидший на будь-якому залізі. Це те, що реально потрібно для мобіля.
| Критерій | Unstructured pruning | Structured pruning |
|---|---|---|
| Зменшення розміру | Значне (стиснення) | Помірне (видалення каналів) |
| Прискорення на CPU/GPU | Мінімальне | Пропорційне видаленим каналам |
| Складність реалізації | Низька | Середня (вимагає синхронізації шарів) |
| Вимагає fine-tuning | Так | Так |
| Підтримка на мобільних пристроях | Обмежена (рідкісні sparse-бібліотеки) | Хороша (будь-який фреймворк) |
Чому structured pruning ефективніший?
Structured pruning фізично зменшує граф обчислень. На мобільних пристроях це дає реальне прискорення інференсу, оскільки не вимагає спеціальних sparse-процесорів. Ми використовуємо L1-норму для ранжування фільтрів і видаляємо найменш значущі. Приклад реалізації на PyTorch:
import torch
import torch.nn.utils.prune as prune
# L1-based structured pruning: видаляємо 30% фільтрів з Conv2d шарів
# за критерієм мінімальної L1-норми (найменш важливі фільтри)
for name, module in model.named_modules():
if isinstance(module, torch.nn.Conv2d):
prune.ln_structured(
module,
name='weight',
amount=0.3, # 30% каналів
n=1, # L1 норма
dim=0 # dim=0 — вихідні фільтри
)
# Після pruning — важливо зробити ваги постійними (прибрати mask)
for name, module in model.named_modules():
if isinstance(module, torch.nn.Conv2d):
prune.remove(module, 'weight')
Після цього модель містить нульові фільтри, але вони все ще в графі. Наступний крок — фактичне видалення нульових каналів:
# Кастомна функція видалення нульових фільтрів
def remove_zero_filters(conv_layer, next_layer=None):
"""Видаляємо фільтри з нульовими вагами і синхронізуємо наступний шар"""
weight = conv_layer.weight.data
# Маска: фільтри з ненульовими вагами
nonzero_mask = weight.abs().sum(dim=(1,2,3)) > 1e-6
conv_layer.weight = nn.Parameter(weight[nonzero_mask])
if conv_layer.bias is not None:
conv_layer.bias = nn.Parameter(conv_layer.bias.data[nonzero_mask])
conv_layer.out_channels = nonzero_mask.sum().item()
# Синхронізуємо наступний шар (вхідні канали)
if next_layer is not None and isinstance(next_layer, nn.Conv2d):
next_layer.weight = nn.Parameter(next_layer.weight.data[:, nonzero_mask])
next_layer.in_channels = nonzero_mask.sum().item()
Це потрібно робити обережно — BatchNorm шари після Conv також містять параметри для кожного каналу і вимагають синхронізації.
Fine-tuning після pruning
Після видалення 20–40% фільтрів модель втрачає точність. Обов'язковий етап — fine-tuning на навчальних даних. Правило: чим агресивніший pruning, тим довший fine-tuning.
# Fine-tuning після pruning — зазвичай 10-20% від початкової кількості епох
optimizer = torch.optim.Adam(pruned_model.parameters(), lr=1e-4) # менший LR
scheduler = torch.optim.lr_scheduler.CosineAnnealingLR(optimizer, T_max=20)
for epoch in range(20):
train_one_epoch(pruned_model, train_loader, optimizer)
val_acc = evaluate(pruned_model, val_loader)
scheduler.step()
print(f"Epoch {epoch}: val_acc={val_acc:.4f}")
Iterative pruning — цикл pruning → fine-tuning → pruning — дає кращий результат, ніж одноразове видалення великої кількості фільтрів.
Lottery Ticket Hypothesis: глибше
Для задач, де результат критичний, використовуємо Lottery Ticket підхід: навчаємо повну мережу, знаходимо «виграшні білети» — sparse subnetworks, які можна навчити до порівнянної точності з нуля. Реалізація через бібліотеку torch_pruning:
import torch_pruning as tp
# Аналіз залежностей між шарами
example_inputs = torch.zeros(1, 3, 224, 224)
DG = tp.DependencyGraph()
DG.build_dependency(model, example_inputs=example_inputs)
# Отримуємо групи пов'язаних шарів (pruning одного вимагає pruning пов'язаних)
pruner = tp.pruner.MagnitudePruner(
model,
example_inputs,
importance=tp.importance.MagnitudeImportance(p=1),
pruning_ratio=0.5, # видалити 50% каналів
global_pruning=False,
iterative_steps=5 # ітеративно за 5 кроків
)
Чому pruning не завжди дає прискорення
MobileNetV3 вже оптимізований: depthwise separable convolutions з малою кількістю каналів. Видалити 30% фільтрів з шару з 16 каналами — отримуємо 11 каналів. Різниця у швидкості — мінімальна, overhead від tensor операцій залишається.
Pruning добре працює на великих моделях: ResNet-50, EfficientNet-B4, BERT. На вже компактних MobileNet/EfficientNet-lite — ефект нижчий. У таких випадках краще почати з легшої базової архітектури, а не прунити важку.
Комбінація з квантизацією
Pruning + квантизація — стандартна двохетапна оптимізація:
- Structured pruning 30–40% → fine-tuning → зменшуємо граф
- INT8 квантизація стиснутого графа → фінальна модель
Приклад результату: EfficientNet-B0 (20 МБ FP32, 80 мс Android) → pruning 35% + INT8 → 4 МБ, 18 мс. Точність top-1 впала з 77.1% до 75.8%.
| Модель | Розмір | Час інференсу | Top-1 точність |
|---|---|---|---|
| Вихідна (FP32) | 20 МБ | 80 мс | 77.1% |
| Після pruning 35% | 13 МБ | 52 мс | 76.5% |
| Після pruning + INT8 | 4 МБ | 18 мс | 75.8% |
Якщо ваша модель вимагає саме таких покращень — ми готові провести повний цикл оптимізації. Зв'яжіться з нами, щоб обговорити проект.
Як ми проводимо pruning під ключ
- Аналіз моделі — визначаємо архітектуру, профілюємо latency та розмір.
- Вибір стратегії pruning — structured або lottery ticket, відсоток видалення.
- Ітеративний pruning + fine-tuning — 3–5 ітерацій з контролем точності.
- Перевірка на цільових пристроях — заміри на реальних смартфонах.
- Опціонально: квантизація — INT8 або FP16 для додаткового стиснення.
- Документація та деплой — надаємо звіт та готову модель.
Приклад використовуваних бібліотек
- PyTorch (torch.nn.utils.prune, torch_pruning)
- TensorFlow Lite (для квантизації)
- ONNX Runtime (для крос-платформенного інференсу)
- Core ML Tools (для iOS)
Що входить в роботу
- Повний цикл оптимізації моделі від аналізу до деплою.
- Structured pruning з fine-tuning.
- Тестування на пристроях замовника (iOS/Android).
- Документація щодо змін архітектури та інструкції з інтеграції.
- Підтримка протягом 30 днів після здачі.
Наш досвід та гарантії
Наші спеціалісти мають багаторічний досвід в оптимізації нейромереж для мобільних пристроїв. Ми успішно провели pruning для 50+ проектів, включаючи додатки з мільйонними аудиторіями. Гарантуємо збереження точності в межах 2% від вихідної за умови дотримання рекомендацій щодо fine-tuning.
Оцінимо ваш проект безкоштовно — просто зв'яжіться з нами. Отримайте консультацію щодо вибору оптимального методу pruning для вашої моделі. Залиште заявку, і ми проаналізуємо вашу модель безкоштовно.
Pruning (artificial neural network) — Wikipedia torch.nn.utils.prune — PyTorch documentation







