چیتشیت
معماریهای CNN و یادگیری انتقالی
CNN Architectures and Transfer Learning
اندازهگذاری کانولوشنها، ساخت LeNet تا ResNet، آموزش کلاسیفایر و فاینتیون بکبون از پیشآموزشدیده. PyTorch و NumPy.
فهرست مطالب
فرمولها
مفهومها- اندازه خروجی
- $H_{out} = \lfloor (H - K + 2P) / S \rfloor + 1$
- پدینگ Same
- $P = (K - 1) / 2$ برای $K$ فرد و $S = 1$.
- پارامترهای کانولوشن
C_out * C_in * K * K + C_out. جمله آخر بایاسها هستند.- میدان دید
- $1 + L (K - 1)$ برای $L$ کانولوشن پشتهم با استراید 1.
- دو 3x3 یا یک 5x5
- میدان دید یکسان 5x5. $18C^2$ در مقابل $25C^2$ پارامتر.
- بلاک باقیمانده
- $y = F(x) + x$. این بلاک همانی را با $F(x) = 0$ یاد میگیرد.
- آنتروپی متقاطع
- $-z_y + \log \sum_j \exp(z_j)$ روی لاجیتهای خام.
- کاهش نرخ یادگیری لایهبهلایه
- $\mathrm{lr}_k = \mathrm{base} \cdot \mathrm{decay}^{L - k}$
چهار خانواده
مفهومها- LeNet-5 (1998)
- کانولوشن، avg pool، لایهی متراکم، tanh. 60٬000 پارامتر.
- AlexNet (2012)
- ReLU، دراپاوت، 5 کانولوشن و 3 لایهی متراکم. 60M پارامتر.
- VGG (2014)
- فقط کانولوشنهای 3x3، 16 یا 19 لایه. 138M پارامتر.
- Inception (2014)
- 1x1، 3x3، 5x5 و pool به صورت موازی، سپس الحاق (concatenate).
- ResNet (2015)
- اتصالات جهشی همانی. آموزش بیش از 100 لایه.
- BasicBlock
- دو کانولوشن 3x3 با یک اتصال جهشی. ResNet-18 و ResNet-34.
- Bottleneck
- 1x1 کاهش، 3x3، 1x1 افزایش. ResNet-50، -101، -152.
- ResNet-18 یا VGG-16
- 11.7M یا 138M پارامتر. دقت Top-1 برابر 69.8٪ یا 71.6٪.
TinyResNet برای ورودی 32x32
معماریResNet BasicBlock
کدpython
self.conv1 = nn.Conv2d(in_c, out_c, kernel_size=3, stride=stride, padding=1, bias=False) # پارامتر beta در BN بایاس را نگه میدارد
self.conv2 = nn.Conv2d(out_c, out_c, kernel_size=3, stride=1, padding=1, bias=False)
if stride != 1 or in_c != out_c:
self.shortcut = nn.Sequential(
nn.Conv2d(in_c, out_c, kernel_size=1, stride=stride, bias=False),
nn.BatchNorm2d(out_c)) # کانولوشن 1x1 ابعاد را هماندازه میکند
else:
self.shortcut = nn.Identity() # اتصال جهشی بدون عملگر (no-op)
out = F.relu(self.bn1(self.conv1(x)))
out = self.bn2(self.conv2(out)) # بدون ReLU قبل از جمع
out = out + self.shortcut(x) # F(x) + x
return F.relu(out)
وظایف در کد
کار و کد| وظیفه | کد |
|---|---|
| اندازه خروجی یک کانولوشن | output_size(h_in, k, p, s) |
| میدان دید دستهای از کانولوشنها | receptive_field(layers) |
| کانولوشن بهصورت یک ضرب ماتریسی | conv2d_im2col(x, w, b, padding=1) |
| اعمال یک کرنل دستی | apply_kernel(x[0], KERNELS["sobel_x"]) |
| میکس کردن یک دسته | mixup_batch(x, y, num_classes, alpha=0.2) |
| تابع زیان (loss) روی برچسبهای نرم | soft_cross_entropy(logits, soft_targets) |
| بکبون منجمد، هد جدید | make_feature_extractor(num_classes=10) |
| حفظ آمارههای متحرک BN | freeze_bn_stats(model) |
یک اپوک آموزش
گامبهگام- افزایش داده
random_hflip()وrandom_crop(pad=4)با reflect pad. فقط مجموعه آموزش. - نرمالسازی
standardize(mean, std)با میانگین و انحراف معیار مجموعه آموزش شما. - دیتالودر
shuffle=Trueبرای آموزش.shuffle=Falseبرای اعتبارسنجی. - مدلاول
model.train(). مدل لاجیتهای خام (N, C) را میدهد. - تابع زیان
soft_cross_entropyبا میکسآپ، در غیر این صورتcross_entropyباlabel_smoothing=0.1. - گام بهینهسازی
optimizer.zero_grad()،loss.backward()،optimizer.step(). - متریکهااضافه کردن
loss.item()، تا گرافی در حافظه باقی نماند. - پایان اپوک
scheduler.step(). سپسmodel.eval()و ارزیابی تحتtorch.no_grad.
فاینتیون با نرخ یادگیری تفکیکی (discriminative LR)
کدpython
model = resnet18(weights=ResNet18_Weights.IMAGENET1K_V1)
model.fc = nn.Linear(model.fc.in_features, 10) # هد جدید
groups = discriminative_param_groups(model, base_lr=1e-3, decay=0.3)
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) # بعد از model.train()
start, unfreeze = progressive_unfreeze_schedule(model)
start() # فقط fc آموزش میبیند
unfreeze(epoch) # اول layer4، بعد layer3
انتخاب روش یادگیری انتقالی
مفهومها- کمتر از 1k تصویر، نزدیک به ImageNet
- بکبون را منجمد کنید. فقط هد را آموزش دهید.
- 1k تا 10k تصویر، نزدیک
- 2 تا 3 مرحله اول را منجمد کنید. بقیه را فاینتیون کنید.
- 10k تا 100k تصویر، هر دامنهای
- فاینتیون سرتاسری با نرخ یادگیری تفکیکی.
- بیش از 100k تصویر، دامنه دور
- همه را فاینتیون کنید. آموزش از صفر را هم در نظر بگیرید.
- در BN با >= 5k نمونه
- BN را در حالت train نگه دارید. آمارههای متحرک خود را بهروزرسانی میکند.
- در BN با دیتاست کوچک
- BN را در حالت eval منجمد کنید. آمارههای ImageNet را نگه دارید.
- دسته بسیار کوچک به ازای هر GPU
- لایه BN را با GroupNorm جایگزین کنید.
- هد برای جایگزینی
backbone.fc(ResNet)،backbone.classifier[1](EfficientNet، MobileNet).
پیشفرضهای آموزش
پیشفرضها| تنظیم | پیشفرض | نکته |
|---|---|---|
SGD `lr` | 0.1 | TinyResNet از صفر، کسینوسی طی 10 اپوک |
momentum | 0.9 | با nesterov=True |
weight_decay | 5e-4 | فاینتیون از 1e-4 استفاده میکند |
label_smoothing | 0.1 | هدف 1-eps برای کلاس واقعی |
Mixup `alpha` | 0.2 | مقدار لاندا از Beta(a, a) |
base_lr | 1e-3 | گروه fc. مراحل اولیه نرخ کمتری میگیرند |
decay | 0.3 | لایه conv1 حدود 0.00243 برابر base_lr دریافت میکند |
batch_size | 128 | لودر اعتبارسنجی از 256 استفاده میکند |
عیبیابی
عیبیابیگرادیان اشتباه، منحنی تخت
- علت
- اعمال Softmax قبل از تابع زیان (loss)
- راهحل
- پاس دادن لاجیتهای خام به
CrossEntropyLoss
شبیه به ناپایداری LR
- علت
- انباشته شدن گرادیانها
- راهحل
- فراخوانی
optimizer.zero_grad()در هر گام
حدود 1٪ افت دقت
- علت
- میانگین و انحراف معیار ImageNet روی CIFAR-10
- راهحل
- محاسبه آمارهها روی مجموعه آموزش خودتان
تبدیل شدن «6» به «9»
- علت
- تغییر برچسب بر اثر افزایش داده
- راهحل
- استفاده از بازههای چرخش کوچکتر
نتیجه فاینتیون بدتر از حالت فقط پیشآموزشدیده
- علت
- باگ LR یا BN
- راهحل
- استفاده از نرخ یادگیری تفکیکی، بررسی حالت BN
افت بیصدای 5 تا 15 درصدی دقت
- علت
- آمارههای BN متعلق به توزیع دیگری است
- راهحل
- منجمد کردن آمارههای BN یا استفاده از GroupNorm
تمام تصاویر یک کلاس را میگیرند
- علت
- نرخ یادگیری فیچرهای از پیشآموزشدیده را از بین میبرد
- راهحل
- کاهش نرخ یادگیری بکبون
آموزش ضعیفتر شبکه ساده و عمیق
- علت
- افت کارایی بعد از حدود 20 لایه
- راهحل
- افزودن اتصالات باقیمانده
پرسشها
پرسش و پاسخ- چرا کرنلهای 3x3؟
- کوچکترین کرنل فرد دارای نقطه مرکز است.
- چگونه بدون pooling ابعاد را کاهش دهیم؟
- از کانولوشن با
stride=2استفاده کنید. ابعاد H و W را نصف میکند. - چرا میکسآپ زیان آموزش را بالا میبرد؟
- برچسبهای هدف نرم هستند. دقت تست افزایش مییابد.
- دو عدد کلیدی برای یادگیری انتقالی کدامند؟
- فقط پیشآموزشدیده کف است. فاینتیونشده سقف است.
- چرا نرخ یادگیری برای لایههای اولیه کمتر است؟
- آنها حامل فیچرهای عمومی مانند لبهها و بافتها هستند.
- چه زمانی اپتیمایزر را دوباره بسازیم؟
- هر بار که مجموعه پارامترهای آموزشپذیر تغییر میکند.
ابعاد لایه کانولوشن
کدpython
conv = nn.Conv2d(in_channels=3, out_channels=64, kernel_size=3, stride=1, padding=1)
tuple(conv.weight.shape) # (C_out, C_in, K, K)
sum(p.numel() for p in conv.parameters()) # 64 * 3 * 3 * 3 + 64 = 1,792
y = conv(torch.randn(8, 3, 224, 224)) # مقدار padding=0 خروجی 222x222 میدهد