آموزش یک شبکهی عصبی عمیق بینایی مانند ResNet از نقطهی صفر، به هزاران ساعت پردازش گرافیکی و حجم عظیمی از دادههای برچسبخورده نیاز دارد. برای بیشتر برنامهنویسان، دسترسی به چنین سختافزارهای سنگینی مقدور یا منطقی نیست. با بهکارگیری یادگیری انتقالی (Transfer Learning)، میتوانیم الگوها و ویژگیهای بصری پایهای را که شرکتهای بزرگ با هزینههای بالا استخراج کردهاند، مستقیماً به پروژهی خود منتقل کنیم.
در ایران، با توجه به دشواری و هزینهی بسیار بالای اجاره یا تهیهی GPUهای ابری خارجی، یادگیری انتقالی اهمیت دوچندانی پیدا میکند. این رویکرد به شما اجازه میدهد حتی با دادههای محدود و روی سیستم شخصی، پردازندههای معمولی (CPU) یا تراشههای در دسترس، مدلهایی با دقت بالا برای کاربردهای بومی مانند پردازش تصاویر پزشکی، صنعتی یا نظارتی بسازید.
در این درس یاد میگیرید که چه زمانی لایههای شبکه را منجمد کنید، چگونه سر کلاسیفایر جدید بسازید و با استفاده از نرخ یادگیری تفکیکی (Discriminative Learning Rate) و مدیریت صحیح نرمالسازی دستهای (BatchNorm)، جلوی خطاهای خاموشی مثل رانش ویژگیها و فراموشی فاجعهبار را بگیرید.
دیگران یک میلیون ساعت پردازش گرافیکی (GPU-hour) صرف کردهاند تا به یک شبکه یاد بدهند لبهها، بافتها و بخشهای اشیا چه شکلی هستند. بهتر است پیش از آموزش مدل خودتان، از همان ویژگیها قرض بگیرید.
اهداف یادگیری
- تشخیص تفاوت استخراج ویژگی (feature extraction) از فاینتیونینگ (fine-tuning) و انتخاب روش مناسب بر اساس اندازهی دیتاست، فاصلهی دامنه (domain distance) و بودجهی محاسباتی
- بارگذاری یک ستون فقرات (backbone) ازپیشآموزشدیده، جایگزینی سرِ کلاسیفایر (classifier head) آن، و آموزش صرفاً همان سر تا رسیدن به یک خط مبنای (baseline) کارآمد در کمتر از 20 خط کد
- یخزدایی تدریجی (progressive unfreezing) لایهها با نرخهای یادگیری تفکیکی (discriminative learning rates)، بهطوریکه ویژگیهای عمومی لایههای اولیه نسبت به ویژگیهای وظیفهمحور لایههای پایانی، بهروزرسانیهای کوچکتری دریافت کنند
- عیبیابی سه مشکل رایج: رانش ویژگی (feature drift) ناشی از نرخ یادگیری بیشازحد بالا در بلوکهای یخزداییشده، فروپاشی آمارههای نرمالسازی دستهای (BatchNorm) روی دیتاستهای بسیار کوچک، و فراموشی فاجعهبار (catastrophic forgetting)
صورت مسئله
آموزش یک ResNet-50 روی ImageNet حدود 2000 ساعت پردازش GPU هزینه دارد. کمتر تیمی برای هر تسکی که دیپلوی میکند چنین بودجهای در اختیار دارد. در عمل، تقریباً همهی تیمها یک ستون فقرات ازپیشآموزشدیده برمیدارند، سرِ جدیدی رویش میگذارند و آن را فقط روی چند صد یا چند هزار تصویرِ مخصوص همان مسئله آموزش میدهند.
این کار صرفاً یک میانبُر نیست. اولین بلوک کانولوشنی هر شبکهی عصبی پیچشی (CNN) آموزشدیده روی ImageNet، لبهها و فیلترهای شبهگابور (Gabor-like) را یاد میگیرد. چند بلوک بعدی بافتها و الگوهای ساده را یاد میگیرند. بلوکهای میانی بخشهای مختلف اشیا را میآموزند و بلوکهای انتهایی هم ترکیبهایی را یاد میگیرند که شبیه به 1000 دستهی ImageNet به نظر میرسند. 90% نخستِ این سلسلهمراتب تقریباً دستنخورده به حوزههای تصویربرداری پزشکی، بازرسی صنعتی، دادههای ماهوارهای و هر وظیفهی بینایی ماشینِ دیگری منتقل میشود — چون طبیعت واژگان محدودی از لبهها و بافتها دارد. آن 10% آخر چیزی است که شما واقعاً باید آموزش دهید.
یادگیری انتقالی (transfer learning) درست، سه تلهی پنهان پیش پای شما میگذارد: نابود کردن ویژگیهای ازپیشآموزشدیده با نرخ یادگیری بیشازحد بالا، محروم کردن مدل از اطلاعات به دلیل منجمد کردن بیشازحد لایهها، و اجازه دادن به آمارههای متحرکِ BatchNorm برای سوق پیدا کردن به سمت دیتاست بسیار کوچکی که سایر بخشهای شبکه هرگز چیزی از آن یاد نگرفتهاند. در این درس عمداً به سراغ تکتک این چالشها میرویم.
مفاهیم پایه
استخراج ویژگی در برابر فاینتیونینگ
دو رویکرد مختلف وجود دارد که بر اساس میزان اعتماد شما به ویژگیهای ازپیشآموزشدیده و حجم دادههایتان انتخاب میشوند.
قواعد سرانگشتی:
| اندازهی دیتاست | فاصلهی دامنه | دستورالعمل |
|---|---|---|
| کمتر از 1k تصویر | نزدیک به ImageNet | ستون فقرات منجمد (freeze)، فقط سرِ مدل آموزش ببیند |
| 1k تا 10k | نزدیک | 2 تا 3 مرحلهی اول منجمد شود، بقیه فاینتیون شوند |
| 10k تا 100k | هر حالتی | فاینتیونینگ سراسری (end-to-end) با نرخ یادگیری تفکیکی |
| بیش از 100k | دور | همهچیز فاینتیون شود؛ اگر دامنه خیلی دور است، آموزش از صفر را بررسی کنید |
«نزدیک به ImageNet» یعنی عکسهای طبیعی RGB با محتوایی از جنس اشیا. سیتیاسکنهای پزشکی، تصاویر هوایی ماهوارهای و تصاویر میکروسکوپی دامنههای دور محسوب میشوند — ویژگیهای قبلی باز هم مفیدند، اما باید بگذارید لایههای بیشتری خود را تطبیق دهند.
چرا انجماد لایهها اصلاً جواب میدهد؟
ویژگیهایی که یک CNN از ImageNet یاد میگیرد به آن 1000 دسته محدود نمیشوند؛ بلکه به آمارههای بنیادینِ تصاویر طبیعی اختصاص یافتهاند: لبهها در زوایای خاص، بافتها، الگوهای کنتراست و ساختارهای اولیهی شکلها. این آمارهها در تقریباً هر دامنهی بصری شناختهشدهای پایدارند. به همین دلیل مدلی که روی ImageNet آموزش دیده، روی CIFAR-10 بهصورت صفر-شات (zero-shot) و صرفاً با یک سرِ خطی جدید (بدون فاینتیونینگ ستون فقرات) به دقت بالای 80% میرسد. سرِ مدل فقط دارد یاد میگیرد به کدامیک از ویژگیهای ازپیشآموخته وزن بدهد.
نرخهای یادگیری تفکیکی
وقتی لایهها را یخزدایی میکنید، لایههای اولیه باید کُندتر از لایههای انتهایی آموزش ببینند. لایههای اولیه ویژگیهای عمومی را کدگذاری کردهاند که میخواهید حفظ شوند؛ لایههای انتهایی ساختارهای مختص وظیفه را دارند که باید تغییرات زیادی بکنند.
Typical recipe:
stage 0 (stem + first group): lr = base_lr / 100 (mostly fixed)
stage 1: lr = base_lr / 10
stage 2: lr = base_lr / 3
stage 3 (last backbone group): lr = base_lr
head: lr = base_lr (or slightly higher)
در PyTorch این کار فقط با ارسال لیستی از گروههای پارامتری (parameter groups) به بهینهساز (optimizer) انجام میشود. یک مدل، پنج نرخ یادگیری، بدون حتی یک خط کد اضافه.
معضل نرمالسازی دستهای (BatchNorm)
لایههای BN دارای بافرهای running_mean و running_var هستند که روی ImageNet محاسبه شدهاند. اگر دادههای مسئلهی شما توزیع پیکسلی متفاوتی داشته باشند — نورپردازی متفاوت، سنسور دیگر، یا فضای رنگی دیگر — این بافرها خطا دارند. سه راهکار به ترتیب اولویت وجود دارد:
- فاینتیونینگ با BN در حالت train. بگذارید BN آمارههای متحرک خود را همراه با بقیهی شبکه بهروز کند. انتخاب پیشفرض برای زمانی که دیتاستِ مسئله متوسط است (حداقل 5k نمونه).
- انجماد BN در حالت eval. آمارههای ImageNet را نگه دارید و فقط وزنها را آموزش دهید. این حالت زمانی درست است که دیتاستتان آنقدر کوچک باشد که میانگین متحرک BN نویز زیادی بگیرد.
- جایگزینی BN با GroupNorm. مشکل میانگین متحرک را بهکل حذف میکند. این کار بیشتر در ستونهای فقرات تشخیص و بخشبندی (segmentation) به کار میرود که اندازهی دسته (batch size) به ازای هر GPU بسیار کوچک است.
اشتباه در این بخش میتواند بیسروصدا دقت مدل را بین 5 تا 15% کاهش دهد.
طراحی سر مدل (Head)
سرِ کلاسیفایر معمولاً از 1 تا 3 لایهی خطی به همراه یک دراپاوت (dropout) اختیاری تشکیل میشود. هر ستون فقرات در torchvision یک سر پیشفرض دارد که شما آن را جایگزین میکنید:
backbone.fc = nn.Linear(backbone.fc.in_features, num_classes) # ResNet
backbone.classifier[1] = nn.Linear(..., num_classes) # EfficientNet, MobileNet
backbone.heads.head = nn.Linear(..., num_classes) # torchvision ViT
برای دیتاستهای کوچک، یک لایهی خطی تکی معمولاً کافی است. افزودن یک لایهی مخفی (Linear -> ReLU -> Dropout -> Linear) زمانی کمک میکند که توزیع دادههای مسئله فاصلهی بیشتری از توزیع دادههای آموزشی ستون فقرات داشته باشد.
کاهش تدریجی لایهای نرخ یادگیری (Layer-wise LR decay)
نسخهی هموارترِ نرخ یادگیری تفکیکی است که در فاینتیونینگهای مدرن (مانند BEiT، DINOv2 و ترنسفورمرهای بینایی ViT-B) استفاده میشود. بهجای گروهبندی لایهها در چند مرحله، به هر لایه نسبت به لایهی بالاتر از خود، نرخ یادگیری کمی کوچکتری اختصاص میدهید:
با نرخ کاهش (decay) برابر 0.75 و 12 بلوک ترنسفورمر (L = 12)، اولین بلوک با نرخ یادگیری معادل 0.75^11 ≈ 0.04x نسبت به سر مدل آموزش میبیند. این موضوع در فاینتیونینگ ترنسفورمرها بسیار حیاتیتر از CNNها است؛ در CNNها معمولاً همان گروهبندی مرحلهای کفایت میکند.
چه مواردی را باید ارزیابی کرد؟
در اجرای یادگیری انتقالی باید دو عدد را ثبت کنید که در آموزش از صفر به آنها نیازی نداشتید:
- دقت فقط ازپیشآموزشدیده (Pretrained-only accuracy) — دقت سرِ مدل در حالتی که ستون فقرات منجمد است. این کفِ عملکرد شماست.
- دقت فاینتیونشده (Fine-tuned accuracy) — عملکرد همان مدل پس از آموزش سراسری. این سقفِ عملکرد شماست.
اگر دقت فاینتیونشده کمتر از دقت فقط ازپیشآموزشدیده باشد، مطمئن باشید در نرخ یادگیری یا تنظیمات BN باگ دارید. همیشه هر دو مقدار را چاپ کنید.
پیادهسازی گامبهگام
مرحلهی 1: بارگذاری یک ستون فقرات ازپیشآموزشدیده و بررسی آن
import torch
import torch.nn as nn
from torchvision.models import resnet18, ResNet18_Weights
backbone = resnet18(weights=ResNet18_Weights.IMAGENET1K_V1)
print(backbone)
print()
print("classifier head:", backbone.fc)
print("feature dim:", backbone.fc.in_features)
مدل ResNet18 چهار مرحله (layer1..layer4) به همراه یک بخش ورودی (stem) و یک سرِ fc دارد. همهی مدلهای پایهی طبقهبندی در torchvision ساختار مشابهی دارند.
مرحلهی 2: استخراج ویژگی — انجماد کامل و تعویض سر مدل
def make_feature_extractor(num_classes=10):
model = resnet18(weights=ResNet18_Weights.IMAGENET1K_V1)
for p in model.parameters():
p.requires_grad = False
model.fc = nn.Linear(model.fc.in_features, num_classes)
return model
model = make_feature_extractor(num_classes=10)
trainable = sum(p.numel() for p in model.parameters() if p.requires_grad)
frozen = sum(p.numel() for p in model.parameters() if not p.requires_grad)
print(f"trainable: {trainable:>10,}")
print(f"frozen: {frozen:>10,}")
اکنون فقط model.fc قابلآموزش است و ستون فقرات نقش یک استخراجکنندهی ویژگیِ منجمد را بازی میکند.
مرحلهی 3: فاینتیونینگ تفکیکی
تابعی کمکی برای ساخت گروههای پارامتری با نرخهای یادگیری اختصاصی به ازای هر مرحله.
def discriminative_param_groups(model, base_lr=1e-3, decay=0.3):
stages = [
["conv1", "bn1"],
["layer1"],
["layer2"],
["layer3"],
["layer4"],
["fc"],
]
groups = []
for i, names in enumerate(stages):
lr = base_lr * (decay ** (len(stages) - 1 - i))
params = [p for n, p in model.named_parameters()
if any(n.startswith(k) for k in names)]
if params:
groups.append({"params": params, "lr": lr, "name": "_".join(names)})
return groups
model = resnet18(weights=ResNet18_Weights.IMAGENET1K_V1)
model.fc = nn.Linear(model.fc.in_features, 10)
for p in model.parameters():
p.requires_grad = True
groups = discriminative_param_groups(model)
for g in groups:
print(f"{g['name']:>10s} lr={g['lr']:.2e} params={sum(p.numel() for p in g['params']):>8,}")
مقدار decay=0.3 به این معنی است که هر مرحله با 30% نرخ یادگیری مرحلهی بعد از خود آموزش میبیند. لایهی fc مقدار base_lr را میگیرد، layer4 مقدار 0.3 * base_lr، و conv1 مقدار 0.3^5 * base_lr ≈ 0.00243 * base_lr را دریافت میکند. شاید شدید به نظر برسد، اما در عمل جواب میدهد.
مرحلهی 4: مدیریت نرمالسازی دستهای (BatchNorm)
یک تابع کمکی برای منجمد نگهداشتن آمارههای متحرک BN بدون انجمادِ وزنهای آن.
def freeze_bn_stats(model):
for m in model.modules():
if isinstance(m, (nn.BatchNorm1d, nn.BatchNorm2d, nn.BatchNorm3d)):
m.eval()
for p in m.parameters():
p.requires_grad = False
return model
این تابع را در شروع هر دورهی آموزشی (epoch)، درست بعد از فراخوانی model.train() صدا بزنید. دستور model.train() همهچیز را به حالت آموزش میبرد؛ این تابع فقط لایههای BN را دوباره به حالت ارزیابی برمیگرداند.
مرحلهی 5: یک حلقهی کمینهی فاینتیونینگ سراسری
from torch.optim import SGD
from torch.utils.data import DataLoader
from torch.optim.lr_scheduler import CosineAnnealingLR
import torch.nn.functional as F
def fine_tune(model, train_loader, val_loader, device, epochs=5, base_lr=1e-3, freeze_bn=False):
model = model.to(device)
groups = discriminative_param_groups(model, base_lr=base_lr)
optimizer = SGD(groups, momentum=0.9, weight_decay=1e-4, nesterov=True)
scheduler = CosineAnnealingLR(optimizer, T_max=epochs)
for epoch in range(epochs):
model.train()
if freeze_bn:
freeze_bn_stats(model)
tr_loss, tr_correct, tr_total = 0.0, 0, 0
for x, y in train_loader:
x, y = x.to(device), y.to(device)
logits = model(x)
loss = F.cross_entropy(logits, y, label_smoothing=0.1)
optimizer.zero_grad()
loss.backward()
optimizer.step()
tr_loss += loss.item() * x.size(0)
tr_total += x.size(0)
tr_correct += (logits.argmax(-1) == y).sum().item()
scheduler.step()
model.eval()
va_total, va_correct = 0, 0
with torch.no_grad():
for x, y in val_loader:
x, y = x.to(device), y.to(device)
pred = model(x).argmax(-1)
va_total += x.size(0)
va_correct += (pred == y).sum().item()
print(f"epoch {epoch} train {tr_loss/tr_total:.3f}/{tr_correct/tr_total:.3f} "
f"val {va_correct/va_total:.3f}")
return model
پنج دورهی آموزشی با دستورالعمل بالا روی CIFAR-10، دقت مدل ResNet18-IMAGENET1K_V1 را از حدود 70% در حالت ارزیابی خطی صفر-شات به حدود 93% در حالت فاینتیونشده میرساند. اگر ستون فقرات را دستنخورده رها میکردید، سرِ مدل بهتنهایی روی حدود 86% متوقف میشد.
مرحلهی 6: یخزدایی تدریجی
یک زمانبندی که در هر دورهی آموزشی، یک مرحله از مدل را از انتها به سمت ابتدا یخزدایی میکند. این روش رانش ویژگیها را با هزینهی چند دورهی آموزشیِ بیشتر مهار میکند.
def progressive_unfreeze_schedule(model):
stages = ["layer4", "layer3", "layer2", "layer1"]
yielded = set()
def start():
for p in model.parameters():
p.requires_grad = False
for p in model.fc.parameters():
p.requires_grad = True
def unfreeze(epoch):
if epoch < len(stages):
name = stages[epoch]
yielded.add(name)
for n, p in model.named_parameters():
if n.startswith(name):
p.requires_grad = True
return name
return None
return start, unfreeze
متد start() را یک بار پیش از دورهی اول صدا بزنید. در ابتدای هر دورهی آموزشی، unfreeze(epoch) را فراخوانی کنید. هر زمان که مجموعهی پارامترهای آموزشپذیر تغییر کرد، بهینهساز را از نو بسازید؛ در غیر این صورت پارامترهای منجمدشده هنوز مقادیر گشتاور (moment) کششدهای دارند که بهینهساز را گیج میکند.
استفاده از ابزارهای واقعی
برای بیشتر کارهای واقعی، ترکیب torchvision.models به همراه سه خط کد کافی است. منطق پیچیدهتری که در بالا بررسی کردیم زمانی اهمیت پیدا میکند که به مشکلاتی بخورید که تنظیمات پیشفرض کتابخانهها قادر به حل آنها نیستند.
from torchvision.models import resnet50, ResNet50_Weights
model = resnet50(weights=ResNet50_Weights.IMAGENET1K_V2)
model.fc = nn.Linear(model.fc.in_features, num_classes)
optimizer = torch.optim.AdamW(model.parameters(), lr=1e-4, weight_decay=1e-4)
دو ابزار استاندارد و آمادهی استفاده در محیطهای عملیاتی:
- کتابخانهی
timmحدود 800 ستون فقرات بینایی ازپیشآموزشدیده را با یک API کاملاً یکپارچه ارائه میدهد (timm.create_model("resnet50", pretrained=True, num_classes=10)). برای هر فاینتیونینگی فراتر از مدلهای torchvision، این کتابخانه گزینهی استاندارد است. - برای ترنسفورمرها، دستور
transformers.AutoModelForImageClassification.from_pretrained(name, num_labels=N)مدلهای ViT ،BEiT یا DeiT را دقیقاً با همان ساختار بارگذاری مدلهای متنی در اختیارتان میگذارد.
خروجی این درس
از این درس به دو خروجی میرسید:
outputs/prompt-fine-tune-planner.md— پرامپتی که بر اساس اندازهی دیتاست، فاصلهی دامنه و بودجهی محاسباتی، بهترین روش را از میان استخراج ویژگی، یخزدایی تدریجی یا فاینتیونینگ سراسری پیشنهاد میدهد.outputs/skill-freeze-inspector.md— مهارتی که با دریافت یک مدل PyTorch گزارش میدهد کدام پارامترها آموزشپذیرند، کدام لایههای BatchNorm در حالت eval هستند، و آیا بهینهساز واقعاً فقط پارامترهای آموزشپذیر را دریافت میکند یا خیر.
تمرینها
- (ساده) مدل
ResNet18را یک بار به عنوان ارزیاب خطی (linear probe با ستون فقرات منجمد) و یک بار بهصورت فاینتیونینگ کامل روی دادههای شبیهسازیشدهی CIFAR آموزش دهید. دقت هر دو حالت را کنار هم گزارش کنید. توضیح دهید کدام فاصلهی دقتی نشاندهندهی انتقال خوب ویژگیهاست و کدام نشان میدهد ویژگیها بهخوبی منتقل نشدهاند. - (متوسط) عمداً یک باگ ایجاد کنید: مقدار
base_lr = 1e-1را بهجای سر مدل، روی مراحل ستون فقرات تنظیم کنید. نشان دهید که چگونه تابع زیان (loss) آموزش منفجر میشود، سپس با اعمال تابع کمکیdiscriminative_param_groupsمدل را بازیابی کنید. نرخ یادگیریای را که در آن هر مرحله شروع به واگرایی میکند ثبت کنید. - (سخت) یک دیتاست تصاویر پزشکی (مانند CheXpert-small ،PatchCamelyon یا HAM10000) بردارید و سه روش را مقایسه کنید: الف) ستون فقرات منجمدِ ازپیشآموزشدیده روی ImageNet به همراه سرِ خطی؛ ب) فاینتیونینگ سراسری ازپیشآموزشدیده روی ImageNet؛ ج) آموزش از صفر. دقت و هزینهی محاسباتی هر کدام را گزارش کنید. در چه اندازهای از دیتاست، آموزش از صفر توان رقابت با بقیه را پیدا میکند؟
اصطلاحات کلیدی
| اصطلاح | در گفتار عامیانه | معنای دقیق فنی |
|---|---|---|
| Feature extraction | «منجمد کردن و آموزشِ سر» | پارامترهای ستون فقرات منجمد هستند و فقط سرِ جدید کلاسیفایر گرادیان دریافت میکند |
| Fine-tuning | «آموزش مجدد از اول تا آخر» | همهی پارامترها آموزشپذیرند، معمولاً با نرخ یادگیری بسیار کمتری نسبت به آموزش از صفر |
| Discriminative LR | «نرخ یادگیری کمتر برای لایههای اول» | گروهبندی پارامترهای بهینهساز بهطوریکه نرخ یادگیری مراحل اولیه کسری از نرخ مراحل انتهایی باشد |
| Layer-wise LR decay | «گرادیان هموارِ نرخ یادگیری» | ضرب نرخ یادگیری هر لایه در decay^(L - k)؛ رایج در فاینتیونینگ ترنسفورمرها |
| Catastrophic forgetting | «مدل اطلاعات ImageNet را از دست داد» | نرخ یادگیری بیشازحد بالا، ویژگیهای ازپیشآموزشدیده را قبل از یادگیری وظیفهی جدید بازنویسی و نابود میکند |
| BN statistics drift | «میانگین متحرک اشتباه است» | مقادیر running_mean/var در لایههای BatchNorm روی توزیعی متفاوت از مسئلهی فعلی محاسبه شدهاند و بیسروصدا به دقت ضربه میزنند |
| Linear probe | «ستون فقرات منجمد + سرِ خطی» | ارزیابی کیفیت ویژگیهای ازپیشآموزشدیده — یعنی دقت بهترین کلاسیفایر خطی که روی این بازنمایی منجمد سوار میشود |
| Catastrophic collapse | «مدل برای همهچیز یک کلاس را پیشبینی میکند» | وقتی رخ میدهد که فاینتیونینگ با چنان نرخ یادگیری بالایی انجام شود که ویژگیها پیش از پایدار شدن گرادیانهای سر مدل نابود شوند |
برای مطالعهی بیشتر
- ویژگیها در شبکههای عصبی عمیق چقدر قابلانتقال هستند؟ (Yosinski et al., 2014) — مقالهای که انتقالپذیری ویژگیها در لایههای مختلف را اندازهگیری کرد.
- فاینتیونینگ مدل زبان فراگیر (ULMFiT, Howard & Ruder, 2018) — دستورالعمل اصلی برای نرخهای یادگیری تفکیکی و یخزدایی تدریجی؛ این ایدهها مستقیماً به بینایی ماشین نیز منتقل میشوند.
- مستندات timm — مرجعی جامع برای ستونهای فقرات مدرن در بینایی و مقادیر پیشفرضی که برای فاینتیونینگ آنها استفاده شده است.
- چارچوبی ساده برای ارزیابی با سر خطی (Kornblith et al., 2019) — چرایی اهمیت دقت در حالت linear-probe و نحوهی گزارش درست آن.
