רשת עצבית ניידת חייבת להיות קלת משקל אך מדויקת. Knowledge Distillation היא שיטה שדוחסת מודל גדול ללא אובדן איכות קריטי. יישמנו גישה זו בעשרות פרויקטים: מסיווג תמונות ועד NLP על המכשיר. התוצאה — מודל קטן פי 10 עם ירידת דיוק של 1–2% בלבד. גישה זו מבוקשת במיוחד ב-ML נייד, שבו כל מגה-בייט וכל אלפית שנייה חשובים. צרו קשר — נבצע ביקורת למודל שלכם ונציע תוכנית distillation.
למה תוויות רכות עובדות טוב יותר
אימון סטנדרטי: מחלקה נכונה = 1.0, אחרות = 0.0. תוויות קשות. מורה על תמונה של חתול מוציא: חתול 0.85, לינקס 0.08, טיגריס 0.04, כלב 0.02 ... תוויות "רכות" אלו נושאות מידע שלינקס דומה יותר לחתול מאשר למטוס. תלמיד שאומן על תוויות כאלה לומד את מבנה מרחב התכונות, לא רק החלטה בינארית של מסווג. זהו המהות של פרדיגמת תלמיד-מורה.
import torch
import torch.nn.functional as F
def distillation_loss(student_logits, teacher_logits, true_labels, temperature=4.0, alpha=0.7):
""" alpha — вес дистилляции vs hard label loss
temperature — сглаживает распределение учителя """
# Soft targets loss (KL divergence между студентом и учителем)
soft_teacher = F.softmax(teacher_logits / temperature, dim=-1)
soft_student = F.log_softmax(student_logits / temperature, dim=-1)
distill_loss = F.kl_div(soft_student, soft_teacher, reduction='batchmean') * (temperature ** 2)
# Hard label loss (обычная кросс-энтропия)
hard_loss = F.cross_entropy(student_logits, true_labels)
return alpha * distill_loss + (1 - alpha) * hard_loss
import torch import torch.nn.functional as F def distillation_loss(student_logits, teacher_logits, true_labels, temperature=4.0, alpha=0.7): """ alpha — вес дистилляции vs hard label loss temperature — сглаживает распределение учителя """ # Soft targets loss (KL divergence между студентом и учителем) soft_teacher = F.softmax(teacher_logits / temperature, dim=-1) soft_student = F.log_softmax(student_logits / temperature, dim=-1) distill_loss = F.kl_div(soft_student, soft_teacher, reduction='batchmean') * (temperature ** 2) # Hard label loss (обычная кросс-энтропия) hard_loss = F.cross_entropy(student_logits, true_labels) return alpha * distill_loss + (1 - alpha) * hard_loss — גורם נורמליזציה שמפצה על קנה המידה של הגרדיאנט בטמפרטורה גבוהה. בלעדיו, distill_loss ו-hard_loss נמצאים בקני מידה שונים.
בחירת ארכיטקטורת תלמיד
התלמיד חייב להיות קטן מהמורה, אך לא באופן שרירותי. ארכיטקטורות בסיס טובות לנייד:
- MobileNetV3-Small — 2.5 MB, מתוכנן לנייד מההתחלה, depthwise separable convolutions
- EfficientNet-Lite0/1 — איזון טוב בין דיוק למהירות
- MobileViT-XXS — היברידי CNN+Transformer, 1.3 MB
- DistilBERT (ל-NLP) — כבר מזוקק מ-BERT, 66 MB לעומת 440 MB
לזיהוי עצמים על נייד: תלמיד מבוסס YOLOv8n (8 MB) מזוקק מ-YOLOv8l (87 MB).
| ארכיטקטורה | פרמטרים | Top-1 ImageNet (distillation) | גודל (FP32) | זמן השהיה (iPhone 13) |
|---|---|---|---|---|
| MobileNetV3-Small | 2.5M | 71–72% | 10 MB | 15 ms |
| EfficientNet-Lite0 | 3.5M | 74–75% | 14 MB | 20 ms |
| MobileViT-XXS | 1.3M | 69–70% | 5.2 MB | 18 ms |
| DistilBERT (NLP) | 66M | ~97% מ-BERT | 264 MB | 30–80 ms |
איך משווים שיטות Distillation?
קיימות מספר גישות distillation, הנבדלות במורכבות ובתוצאה. העיקריות: logit distillation (על פלטים), distillation של שכבות ביניים, ו-data-free distillation. הבחירה תלויה בזמינות הנתונים ובדרישות הדיוק.
| שיטה | אימון תלמיד | נתונים נדרשים | מורכבות | ירידת דיוק אופיינית |
|---|---|---|---|---|
| Logit distillation | על תוויות רכות של המורה | מערך נתונים מלא | נמוכה | 1-2% |
| Feature (intermediate) distillation | על פלטים של שכבות ביניים | מערך נתונים מלא | בינונית | 0.5-1% |
| Data-free distillation | על נתונים סינתטיים | אין | גבוהה | 2-5% |
שלבי Distillation
- הכנת מורה: fine-tune או קוונטיזציה של מודל קיים, הקפאת משקלים.
- בחירת ארכיטקטורת תלמיד: התאמה לתקציב משאבים (RAM, CPU, זמן השהיה).
- כוונון היפרפרמטרים: טמפרטורה (בדרך כלל 2-8), alpha (0.5-0.9), בחירת שכבות ל-intermediate distillation.
- אימון תלמיד: מזעור loss משולב, ניטור דיוק ולידציה.
- המרה ל-Core ML/TFLite עם קוונטיזציה int8 לגודל סופי.
- ולידציה על מכשירים אמיתיים: בדיקת זמן השהיה ודיוק.
תהליך Distillation: דוגמה לסיווג
# Предположим: учитель — ResNet-50, студент — MobileNetV3-Small
teacher = torchvision.models.resnet50(pretrained=True).eval()
student = torchvision.models.mobilenet_v3_small(pretrained=False)
# Замораживаем учителя
for param in teacher.parameters():
param.requires_grad = False
optimizer = torch.optim.AdamW(student.parameters(), lr=1e-3, weight_decay=1e-4)
scheduler = torch.optim.lr_scheduler.CosineAnnealingLR(optimizer, T_max=100)
for epoch in range(100):
student.train()
for images, labels in train_loader:
with torch.no_grad():
teacher_logits = teacher(images)
student_logits = student(images)
loss = distillation_loss(student_logits, teacher_logits, labels, temperature=4.0, alpha=0.7)
optimizer.zero_grad()
loss.backward()
optimizer.step()
scheduler.step()
val_acc = evaluate(student, val_loader)
print(f"Epoch {epoch}: student_acc={val_acc:.4f}")תוצאות אופייניות: MobileNetV3-Small שאומן רגיל — 67–68% top-1 על ImageNet. לאחר distillation מ-ResNet-50 — 71–72%. עלייה של 3–4% בזכות העברת ידע.
איך עובדת Distillation של שכבות ביניים?
Distillation רק על פלטים (logits) היא הגרסה הבסיסית. גרסה חזקה יותר: הוספת התאמה של מפות תכונות ביניים.
# FitNets / PKT: студент учит feature maps учителя
class DistillationHook:
"""Хук для захвата промежуточных активаций"""
def __init__(self):
self.output = None
def __call__(self, module, input, output):
self.output = output
teacher_hook = DistillationHook()
student_hook = DistillationHook()
# Регистрируем на соответствующих слоях
teacher.layer3.register_forward_hook(teacher_hook)
student.features[9].register_forward_hook(student_hook) # Analogous layer
# В цикле обучения добавляем feature distillation loss
with torch.no_grad():
teacher(images)
teacher_features = teacher_hook.output
student(images) # с grad
student_features = student_hook.output
# Если размерности отличаются — нужен adapter (1x1 Conv)
if teacher_features.shape[1] != student_features.shape[1]:
student_features = adapter_conv(student_features) # adapter обучается вместе
feature_loss = F.mse_loss(student_features, teacher_features.detach())גישה זו דורשת יישור ממדי מפות התכונות בין מורה לתלמיד — באמצעות מתאמים קונבולוציוניים 1×1. המתאם מוסיף כמה פרמטרים לתלמיד אך נשאר קטן.
איך לזקק מודל אם הנתונים המקוריים אינם זמינים?
לפעמים מערך הנתונים המקורי אינו זמין (הגבלות IP, פרטיות). Data-free distillation — יצירת נתונים סינתטיים שממקסמים את ההפעלות של המורה:
# DAFL (Data-Free Learning): генератор создаёт «образцы» для дистилляции
generator = Generator(latent_dim=256, img_channels=3)
optimizer_G = torch.optim.Adam(generator.parameters(), lr=1e-4)
for step in range(1000):
z = torch.randn(batch_size, 256)
fake_images = generator(z)
# Потери: максимизируем уверенность учителя + минимизируем BatchNorm statistics mismatch
teacher_out = teacher(fake_images)
activation_loss = -teacher_out.max(dim=1)[0].mean() # учитель должен быть уверен
# BN statistics matching
bn_loss = compute_bn_statistics_loss(teacher, fake_images)
total_loss = activation_loss + 0.1 * bn_loss
optimizer_G.zero_grad()
total_loss.backward()
optimizer_G.step()
האיכות של data-free distillation נמוכה יותר מהגרסה עם נתונים מלאים, אך לפעמים זו האפשרות היחידה.
Distillation למשימות NLP על נייד
לאפליקציות ניידות עם NLP (סיווג סנטימנט, זיהוי כוונה, סיכום): לזקק מתגובות GPT-4 / Claude API ל-BERT/DistilBERT קטן.
# Собираем soft labels от учителя (GPT-4 API)
# Для каждого обучающего примера запрашиваем вероятности классов
# Сохраняем как обучающие метки для студента
# Студент — DistilBERT fine-tuned на этих мягких меткахDistilBERT (66 MB, ONNX int8 — 18 MB) רץ על המכשיר ב-30–80 ms על iOS/Android. GPT-4 בענן — מאות ms, ועלות לכל בקשה.
מה כלול בעבודה שלנו
- ניתוח תקציב משאבים: RAM, CPU, GPU, צריכת חשמל
- בחירת ארכיטקטורת תלמיד לפי האילוצים שלכם
- הכנת מורה (fine-tuning, קוונטיזציה)
- Distillation עם כוונון היפרפרמטרים (טמפרטורה, alpha, שכבות ביניים)
- ולידציה על ערכת בדיקה ועל מכשירים אמיתיים
- המרה ל-Core ML / TFLite עם קוונטיזציה int8
- אינטגרציה ותמיכה (עדכונים לגרסאות OS חדשות)
לצוות שלנו ניסיון של 10+ שנים בפיתוח נייד ו-ML. אנו מבטיחים שהמודל ירוץ ביציבות על iOS 14+ ו-Android 10+. קבלו ייעוץ הנדסי על המודל שלכם. הזמינו distillation — נכין הערכה ראשונית תוך יום אחד.
הערכות זמנים
Logit distillation בסיסי למשימת סיווג — 2–4 שבועות (זמן GPU בתוספת כוונון היפרפרמטרים). Distillation מלא עם שכבות ביניים, ארכיטקטורות לא סטנדרטיות, הגדלת נתונים — 5–10 שבועות. הערכה מותאמת אישית לפי בקשה.
קריאה נוספת: Knowledge Distillation בוויקיפדיה, מדריך PyTorch.







