در طراحی سیستمهای بینایی ماشین، انتخاب نادرست معماری مدل هزینههای پردازشی سنگینی به بار میآورد. بسیاری از توسعهدهندگان بدون ارزیابی نیاز مسئله، به سراغ بزرگترین مدلهای موجود میروند؛ در حالی که شناخت سیر تکامل شبکههای عصبی پیچشی (CNN) نشان میدهد هر جهش تاریخی، پاسخی به یک محدودیت ساختاری مشخص بوده است.
این درس به شما کمک میکند خط تکامل LeNet-5 ،AlexNet ،VGG ،Inception و ResNet را بشناسید و درک کنید که چرا ایدهای ساده مثل اتصالات باقیمانده (residual connections)، بنبست افزایش عمق شبکهها را حل کرد. این آموختهها پایهی شناخت بکبونهای مدرن بینایی ماشین و حتی معماریهای ترنسفورمر امروزی است.
تمام شبکههای عصبی پیچشی (CNN) مطرح سی سال گذشته از همان دستورالعمل همیشگی «کانولوشن–غیرخطیسازی–کاهش نمونهبرداری» پیروی میکنند و فقط یک ایدهی جدید به آن اضافه کردهاند. این ایدهها را به ترتیب یاد بگیرید.
اهداف یادگیری
- ردگیری مسیر تکامل معماریها از LeNet-5 به AlexNet، VGG، Inception و در نهایت ResNet، و بیان تکایدهی محوری هر خانواده
- پیادهسازی LeNet-5، یک بلوک به سبک VGG و یک BasicBlock در ResNet با PyTorch (هر کدام در کمتر از 40 خط کد)
- توضیح دلیل اینکه چرا اتصالات باقیمانده (residual connections) یک شبکهی 1,000 لایهایِ آموزشناپذیر را به پیشرفتهترین مدل روز تبدیل میکنند
- بررسی ساختار یک ستونفقرات یا بکبون (backbone) مدرن مثل ResNet-18 یا ResNet-50 و پیشبینی ابعاد خروجی، میدان دید (receptive field) و تعداد پارامترهای آن، پیش از نگاه کردن به سورسکد
صورت مسئله
در سال 2011، بهترین کلاسیفایر روی مجموعهدادهی ImageNet به دقتِ top-5 حدود 74% رسید. در سال 2012، AlexNet این عدد را به 85% رساند و در سال 2015، ResNet رکورد 96% را ثبت کرد. نه دادهی جدیدی در کار بود و نه نسل تازهای از پردازندههای گرافیکی (GPU). تمام این پیشرفتها حاصل ایدههای معماری بود. هر مهندس بینایی ماشین باید بداند کدام ایده از کدام مقاله آمده است؛ چون هر بکبونی که در سال 2026 به محیط پروداکشن میفرستید، ترکیبی از همین تکههاست. علاوه بر این، این مفاهیم مدام به حوزههای دیگر منتقل میشوند: کانولوشنهای گروهی از CNNها وارد ترنسفورمرها شدند، اتصالات باقیمانده از ResNet به تکتک مدلهای زبانی بزرگ (LLM) امروزی راه یافتند و نرمالسازی دستهای (batch normalization) هنوز در مدلهای دیفیوژن زنده است.
مطالعهی این شبکهها به ترتیب تاریخی، شما را در برابر یک اشتباه رایج واکسینه میکند: دست بردن به سمت بزرگترین مدل موجود، در حالی که شبکهای در ابعاد LeNet مسئله را حل میکند. پایگاه دادهی MNIST نیازی به ResNet ندارد. شناخت منحنی مقیاسپذیری هر خانواده به شما میگوید کجای این طیف بایستید.
مفاهیم پایه
چهار ایدهای که بینایی ماشین را دگرگون کردند
در بینایی ماشین کلاسیک، هیچ چیز به اندازهی این چهار جهش اهمیت نداشته است.
شبکه LeNet-5 (سال 1998)
سیستم بازشناسی ارقام دستنویس یان لکان (Yann LeCun). دارای 60,000 پارامتر، دو بلوک کانولوشن-ادغام (conv-pool)، دو لایهی کاملاً متصل (fully connected) و توابع فعالساز tanh. این شبکه الگویی را ساخت که به ارث تمام CNNهای بعدی تبدیل شد:
input (1, 32, 32)
conv 5x5 -> (6, 28, 28)
avg pool 2x2 -> (6, 14, 14)
conv 5x5 -> (16, 10, 10)
avg pool 2x2 -> (16, 5, 5)
flatten -> 400
dense -> 120
dense -> 84
dense -> 10
هر چیزی که امروز در دنیای مدرن CNN نامیده میشود — تکرار متناوب کانولوشن و کاهش نمونهبرداری (downsampling) که به یک سر کلاسیفایرِ کوچک ختم میشوند — همان LeNet است؛ فقط با لایههای بیشتر، کانالهای فراختر و توابع فعالساز کارآمدتر.
شبکه AlexNet (سال 2012)
سه تغییر کلیدی که در کنار هم رکورد ImageNet را شکستند:
- تابع ReLU به جای tanh. دیگر خبری از محوشدگی گرادیان (vanishing gradient) نبود و سرعت آموزش 6 برابر شد.
- لایه Dropout در بخش کاملاً متصل انتهایی. تنظیمگری (regularization) به یک لایهی مستقل تبدیل شد، نه صرفاً یک ترفند محاسباتی.
- عمق و پهنای بیشتر. پنج لایهی کانولوشن، سه لایهی متراکم (dense layer)، 60 میلیون پارامتر؛ آموزشدیده روی دو پردازندهی گرافیکی که مدل بین آنها تقسیم شده بود.
شکل 2 در مقالهی اصلی هنوز این تقسیم روی GPU را بهصورت دو جریان موازی نشان میدهد. این موازیسازی یک راهکار سختافزاری بود، نه یک بینش معماری؛ اما آن سه ایدهی اصلی هنوز در تمام مدلهای امروزی حضور دارند.
شبکه VGG (سال 2014)
پژوهشگران VGG این پرسش را مطرح کردند: اگر فقط از کانولوشنهای 3x3 استفاده کنیم و شبکه را بسیار عمیق بسازیم، چه میشود؟
stack: conv 3x3 -> conv 3x3 -> pool 2x2
repeat: 16 or 19 conv layers
دو کانولوشن 3x3 پشت سر هم، همان ناحیهی ورودی 5x5 را میبینند که یک کانولوشن 5x5 پوشش میدهد؛ اما با پارامترهای کمتر ( در برابر ) و یک لایه ReLU اضافی در میان آنها. VGG این مشاهده را تبدیل به یک معماری کامل کرد. سادگی کار — تکرار مداومِ تنها یک نوع بلوک — آن را به نقطهی مرجع تمام مدلهای بعد از خود بدل کرد.
بهای این کار: 138 میلیون پارامتر، سرعت آموزش پایین و هزینهی پردازشی سنگین در زمان استنتاج (inference).
شبکه Inception (سال 2014، همان سال)
پاسخ گوگل به این پرسش که «از چه اندازهی کرنلی استفاده کنم؟» این بود: همهی اندازهها، بهصورت موازی.
هر شاخه (branch) تخصصی عمل میکند: کرنل 1x1 برای ترکیب کانالها، 3x3 برای بافتهای محلی، 5x5 برای الگوهای بزرگتر و ادغام (pooling) برای استخراج ویژگیهای ناوردا نسبت به جابهجایی. در نهایت لایهی الحاق (concat) به لایهی بعد اجازه میدهد هر شاخهای را که مفیدتر است انتخاب کند. Inception v1 از کانولوشنهای 1x1 در داخل هر شاخه به عنوان گلوگاه (bottleneck) استفاده کرد تا تعداد پارامترها منطقی بماند.
مسئله افت عملکرد (Degradation Problem)
تا سال 2015، مدل VGG-19 بهخوبی کار میکرد، اما VGG-32 شکست میخورد. قرار بود افزایش عمق به بهبود مدل کمک کند، اما فراتر از حدود 20 لایه، تابع زیان (loss) در هر دو مرحلهی آموزش و آزمون بدتر میشد. پای بیشبرازش (overfitting) در میان نبود؛ بهینهساز به این دلیل در پیدا کردن وزنهای کارآمد شکست میخورد که گرادیانها در گذر از هر لایه بهصورت ضربی کوچک میشدند و افت میکردند.
Plain deep network:
y = f_L( f_{L-1}( ... f_1(x) ... ) )
Gradient wrt early layer:
dL/dW_1 = dL/dy * df_L/df_{L-1} * ... * df_2/df_1 * df_1/dW_1
Each multiplicative term has magnitude roughly (weight magnitude) * (activation gain).
Stack 100 of them with gains < 1 and the gradient is effectively zero.
مدل VGG در 19 لایه به این دلیل جواب داد که نرمالسازی دستهای (که همزمان معرفی شده بود) مقیاس فعالسازیها را در دامنهای مناسب نگه میداشت. اما حتی نرمالسازی دستهای هم نتوانست عمق فراتر از حدود 30 لایه را نجات دهد.
شبکه ResNet (سال 2015)
تیم پژوهشی شامل He، Zhang، Ren و Sun یک تغییر را پیشنهاد دادند که همه چیز را حل کرد:
عبارت + x یعنی لایه همیشه میتواند با صفر کردن F(x)، خروجی را بدون تغییر رد کند و دست به کاری نزند. حالا یک ResNet با 1,000 لایه در بدترین حالت عملکردی مشابه یک شبکهی 1 لایهای دارد، چون هر بلوکِ اضافه یک مسیر فرار ساده در اختیار دارد. با این تضمین، بهینهساز میتواند هر بلوک را کمی مفیدتر کند؛ و همین فایدههای اندک وقتی در 100 لایه روی هم قرار میگیرند، رکوردهای جهانی را جابهجا میکنند.
دو نسخهی پرکاربرد از این بلوک همهجا دیده میشوند:
- بلوک BasicBlock (در ResNet-18 و ResNet-34): دو کانولوشن 3x3 به همراه یک اتصال جهشی (skip connection) دور هر دو.
- بلوک Bottleneck (در ResNet-50، ResNet-101 و ResNet-152): لایهی 1x1 برای کاهش، 3x3 در میانه، 1x1 برای افزایش، همراه با اتصال جهشی دور این سه لایه. این روش هنگام بالا بودن تعداد کانالها بسیار کمهزینهتر است.
وقتی اتصال جهشی باید از روی یک مرحلهی کاهش نمونهبرداری (stride=2) عبور کند، مسیر همانی (identity) با یک کانولوشن 1x1 با گام 2 جایگزین میشود تا ابعاد تنسورها همخوان شوند.
اهمیت اتصالات باقیمانده فراتر از بینایی ماشین
این ایده صرفاً مربوط به دستهبندی تصویر نبود؛ بلکه شبکههای عمیق را از یک بازی شانسی مبتنی بر «دعا کنیم گرادیان سالم برسد» به ابزاری مهندسی، قابل اعتماد و مقیاسپذیر تبدیل کرد. تکتک مدلهای ترنسفورمری که در فاز بعدی بررسی میکنیم، دقیقاً همین اتصال جهشی را در تکتک بلوکهای خود دارند. بدون ResNet، مدلی به نام GPT وجود نداشت.
پیادهسازی از صفر
گام 1: پیادهسازی LeNet-5
یک پیادهسازی مینیمال و وفادار به ساختار اصلی LeNet؛ همراه با توابع فعالساز tanh و ادغام میانگینگیر (average pooling). تنها سازش ما با متدهای مدرن، استفاده از nn.CrossEntropyLoss در خروجی به جای اتصالات گاوسی نسخهی اصلی است.
import torch
import torch.nn as nn
import torch.nn.functional as F
class LeNet5(nn.Module):
def __init__(self, num_classes=10):
super().__init__()
self.conv1 = nn.Conv2d(1, 6, kernel_size=5)
self.conv2 = nn.Conv2d(6, 16, kernel_size=5)
self.pool = nn.AvgPool2d(2)
self.fc1 = nn.Linear(16 * 5 * 5, 120)
self.fc2 = nn.Linear(120, 84)
self.fc3 = nn.Linear(84, num_classes)
def forward(self, x):
x = self.pool(torch.tanh(self.conv1(x)))
x = self.pool(torch.tanh(self.conv2(x)))
x = torch.flatten(x, 1)
x = torch.tanh(self.fc1(x))
x = torch.tanh(self.fc2(x))
return self.fc3(x)
net = LeNet5()
x = torch.randn(1, 1, 32, 32)
print(f"output: {net(x).shape}")
print(f"params: {sum(p.numel() for p in net.parameters()):,}")
خروجی مورد انتظار: output: torch.Size([1, 10]) و params: 61,706. این تمام کلاسیفایر ارقامی است که بینایی ماشین مدرن را پایهگذاری کرد.
گام 2: پیادهسازی یک بلوک به سبک VGG
یک بلوک با قابلیت استفادهی مجدد: دو کانولوشن 3x3، تابع ReLU، نرمالسازی دستهای و ادغام بیشینه (max pool).
class VGGBlock(nn.Module):
def __init__(self, in_c, out_c):
super().__init__()
self.conv1 = nn.Conv2d(in_c, out_c, kernel_size=3, padding=1)
self.bn1 = nn.BatchNorm2d(out_c)
self.conv2 = nn.Conv2d(out_c, out_c, kernel_size=3, padding=1)
self.bn2 = nn.BatchNorm2d(out_c)
self.pool = nn.MaxPool2d(2)
def forward(self, x):
x = F.relu(self.bn1(self.conv1(x)))
x = F.relu(self.bn2(self.conv2(x)))
return self.pool(x)
class MiniVGG(nn.Module):
def __init__(self, num_classes=10):
super().__init__()
self.stack = nn.Sequential(
VGGBlock(3, 32),
VGGBlock(32, 64),
VGGBlock(64, 128),
)
self.head = nn.Sequential(
nn.AdaptiveAvgPool2d(1),
nn.Flatten(),
nn.Linear(128, num_classes),
)
def forward(self, x):
return self.head(self.stack(x))
net = MiniVGG()
x = torch.randn(1, 3, 32, 32)
print(f"output: {net(x).shape}")
print(f"params: {sum(p.numel() for p in net.parameters()):,}")
سه بلوک VGG روی ورودی در ابعاد CIFAR، یک ادغام تطبیقی (adaptive pool) و یک لایهی خطی؛ با حدود 290 هزار پارامتر که برای CIFAR-10 کاملاً کافی است.
گام 3: پیادهسازی BasicBlock در ResNet
بلوک ساختمانی اصلی برای شبکههای ResNet-18 و ResNet-34.
class BasicBlock(nn.Module):
def __init__(self, in_c, out_c, stride=1):
super().__init__()
self.conv1 = nn.Conv2d(in_c, out_c, kernel_size=3, stride=stride, padding=1, bias=False)
self.bn1 = nn.BatchNorm2d(out_c)
self.conv2 = nn.Conv2d(out_c, out_c, kernel_size=3, stride=1, padding=1, bias=False)
self.bn2 = nn.BatchNorm2d(out_c)
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),
)
else:
self.shortcut = nn.Identity()
def forward(self, x):
out = F.relu(self.bn1(self.conv1(x)))
out = self.bn2(self.conv2(out))
out = out + self.shortcut(x)
return F.relu(out)
تنظیم bias=False در لایههای کانولوشن یک قرارداد مرسوم در کنار نرمالسازی دستهای است؛ پارامتر بتای نرمالسازی دستهای کار بایاس را انجام میدهد، بنابراین نگهداشتن بایاس در کانولوشن صرفاً هدر دادن منابع است. متغیر shortcut تنها زمانی به یک لایهی کانولوشن واقعی نیاز دارد که گام حرکتی (stride) یا تعداد کانالها تغییر کند؛ در غیر این صورت یک نگاشت همانی بدون هزینه (no-op) خواهد بود.
گام 4: ساخت یک مدل ResNet کوچک
قرار دادن چهار گروه از بلوکهای BasicBlock روی هم برای ساخت یک ResNet کاربردی متناسب با ابعاد ورودی CIFAR.
class TinyResNet(nn.Module):
def __init__(self, num_classes=10):
super().__init__()
self.stem = nn.Sequential(
nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1, bias=False),
nn.BatchNorm2d(32),
nn.ReLU(inplace=True),
)
self.layer1 = self._make_group(32, 32, num_blocks=2, stride=1)
self.layer2 = self._make_group(32, 64, num_blocks=2, stride=2)
self.layer3 = self._make_group(64, 128, num_blocks=2, stride=2)
self.layer4 = self._make_group(128, 256, num_blocks=2, stride=2)
self.head = nn.Sequential(
nn.AdaptiveAvgPool2d(1),
nn.Flatten(),
nn.Linear(256, num_classes),
)
def _make_group(self, in_c, out_c, num_blocks, stride):
blocks = [BasicBlock(in_c, out_c, stride=stride)]
for _ in range(num_blocks - 1):
blocks.append(BasicBlock(out_c, out_c, stride=1))
return nn.Sequential(*blocks)
def forward(self, x):
x = self.stem(x)
x = self.layer1(x)
x = self.layer2(x)
x = self.layer3(x)
x = self.layer4(x)
return self.head(x)
net = TinyResNet()
x = torch.randn(1, 3, 32, 32)
print(f"output: {net(x).shape}")
print(f"params: {sum(p.numel() for p in net.parameters()):,}")
چهار گروه که هر کدام دو بلوک دارند. گام حرکتی 2 در ابتدای گروههای 2، 3 و 4 اعمال میشود. تعداد کانالها با هر بار کاهش ابعاد، دو برابر میشود. این شبکه تقریباً 2.8 میلیون پارامتر دارد. این همان فرمول استانداردی است که به شکلی تمیز تا ResNet-152 مقیاسپذیر میشود.
گام 5: مقایسهی کارایی پارامترها نسبت به استخراج ویژگی
ارسال یک ورودی یکسان به هر سه شبکه و مقایسهی تعداد پارامترهای آنها.
def summary(name, net, x):
y = net(x)
params = sum(p.numel() for p in net.parameters())
print(f"{name:12s} input {tuple(x.shape)} -> output {tuple(y.shape)} params {params:>10,}")
x = torch.randn(1, 3, 32, 32)
summary("LeNet5", LeNet5(), torch.randn(1, 1, 32, 32))
summary("MiniVGG", MiniVGG(), x)
summary("TinyResNet", TinyResNet(), x)
سه مدل، سه دوره و سه مرتبهی بزرگی در تعداد پارامترها. برای رسیدن به دقت مناسب روی CIFAR-10 پس از چند دور آموزش، وضعیت تقریبی چنین خواهد بود: مدل LeNet حدود 60%، مدل MiniVGG حدود 89% و TinyResNet حدود 93%.
استفاده از ابزارهای واقعی
کتابخانهی torchvision.models نسخههای از پیش آموزشدیدهی (pretrained) تمام این مدلها را در اختیارتان میگذارد. ساختار فراخوانی در همهی این خانوادهها یکسان است، و اتفاقاً هدف اصلی مفهوم انتزاعی بکبون هم همین است.
from torchvision.models import resnet18, ResNet18_Weights, vgg16, VGG16_Weights
r18 = resnet18(weights=ResNet18_Weights.IMAGENET1K_V1)
r18.eval()
print(f"ResNet-18 params: {sum(p.numel() for p in r18.parameters()):,}")
print(r18.layer1[0])
print()
v16 = vgg16(weights=VGG16_Weights.IMAGENET1K_V1)
v16.eval()
print(f"VGG-16 params: {sum(p.numel() for p in v16.parameters()):,}")
مدل ResNet-18 حدود 11.7 میلیون پارامتر دارد؛ در حالی که VGG-16 دارای 138 میلیون پارامتر است، اما دقت top-1 آنها روی ImageNet تقریباً در یک سطح است (69.8% در برابر 71.6%). اتصالات باقیمانده بازدهی پارامترها را 12 برابر بهتر میکنند. به همین دلیل مشتقات ResNet از سال 2016 تا زمان ظهور ViT در سال 2021 بر این حوزه مسلط بودند — و هنوز هم در محیطهای عملیاتی واقعی که محدودیت پردازشی دارند، انتخاب اول محسوب میشوند.
برای یادگیری انتقالی (transfer learning)، دستورالعمل همیشه ثابت است: بارگذاری وزنهای از پیش آموزشدیده، فریز کردن بکبون و جایگزین کردن سر کلاسیفایر.
for p in r18.parameters():
p.requires_grad = False
r18.fc = nn.Linear(r18.fc.in_features, 10)
تنها سه خط کد. حالا یک کلاسیفایر 10 کلاسه برای CIFAR دارید که از همان بازنماییهای آموزشدیده روی ImageNet بهره میبرد.
خروجی این درس
این درس فایلهای زیر را تولید میکند:
outputs/prompt-backbone-selector.md— یک پرامپت برای انتخاب خانوادهی مناسب CNN (شامل LeNet، VGG، ResNet، MobileNet و ConvNeXt) بر اساس نوع تسک، حجم داده و محدودیت منابع پردازشی.outputs/skill-residual-block-reviewer.md— مهارتی که کدهای ماژول PyTorch را بررسی میکند و خطاهای اتصالات جهشی را تشخیص میدهد (مانند جا افتادن shortcut هنگام تغییر stride، ترتیب اعمال فعالساز در مسیر میانبر، و موقعیت قرارگیری نرمالسازی دستهای نسبت به عمل جمع).
تمرینها
- (ساده) پارامترهای مدل
TinyResNetرا لایه به لایه بهصورت دستی محاسبه کنید. نتیجه را با خروجیsum(p.numel() for p in net.parameters())بسنجید. بیشترین سهم پارامترها به کدام بخش اختصاص دارد: کانولوشنها، نرمالسازی دستهای یا سر کلاسیفایر؟ - (متوسط) بلوک Bottleneck را (مسیر 1x1 -> 3x3 -> 1x1 به همراه اتصال جهشی) پیادهسازی کنید و از آن برای ساخت شبکهای به سبک ResNet-50 برای مجموعهدادهی CIFAR بهره ببرید. تعداد پارامترهای آن را با
TinyResNetمقایسه کنید. - (سخت) اتصال جهشی را از
BasicBlockحذف کنید؛ سپس یک شبکهی بدون اتصالِ 34 بلوکی و یک ResNet استاندارد 34 بلوکی را به مدت 10 دور (epoch) روی CIFAR-10 آموزش دهید. نمودار تابع زیان آموزش بر حسب epoch را برای هر دو رسم کنید. نتیجهی شکل 1 در مقالهی He و همکاران را بازتولید کنید؛ جایی که شبکهی عمیقِ بدون اتصال جهشی، نسبت به همتای کمعمقتر خود در مقدار زیان بالاتری همگرا میشود.
اصطلاحات کلیدی
| اصطلاح | آنچه افراد میگویند | معنای واقعی آن |
|---|---|---|
| بکبون (Backbone) | «خودِ مدل» | مجموعهای از بلوکهای کانولوشنی که نقشهی ویژگی (feature map) را برای ارسال به سرِ تسک میسازد |
| اتصال باقیمانده (Residual connection) | «اتصال جهشی (skip connection)» | فرمول y = F(x) + x؛ به بهینهساز اجازه میدهد با صفر کردن تابع F، تابع همانی را یاد بگیرد؛ قابلیتی که آموزش عمقهای دلخواه را ممکن میکند |
| بلوک BasicBlock | «دو کانولوشن 3x3 با یک پرش» | بلوک سازندهی ResNet-18 و ResNet-34: شامل کانولوشن-BN-ReLU-کانولوشن-BN-جمع-ReLU |
| بلوک Bottleneck | «1x1 کاهشی، 3x3، 1x1 افزایشی» | بلوک شبکههای ResNet-50/101/152؛ در کانالهای زیاد بسیار بهصرفه است، چون کانولوشن 3x3 روی پهنای کاهشیافته اجرا میشود |
| مسئله افت عملکرد (Degradation problem) | «شبکه عمیقتر، نتیجه بدتر» | فراتر از حدود 20 لایهی کانولوشن معمولی، خطای آموزش و آزمون هر دو بالا میروند؛ راهحل آن اتصالات باقیمانده است، نه دادهی بیشتر |
| ساقه (Stem) | «لایهی اول» | کانولوشن ابتدایی که ورودی 3 کاناله را به پهنای ویژگی پایه تبدیل میکند؛ معمولاً 7x7 با گام 2 برای ImageNet و 3x3 با گام 1 برای CIFAR |
| سر (Head) | «کلاسیفایر» | لایههای پس از آخرین بلوک بکبون: شامل ادغام تطبیقی، مسطحسازی (flatten) و لایههای خطی |
| یادگیری انتقالی (Transfer learning) | «وزنهای از پیش آموزشدیده» | بارگذاری بکبونی که روی ImageNet آموزش دیده و فاینتیونینگ اختصاصیِ بخش سر برای مسئلهی شما |
برای مطالعهی بیشتر
- Deep Residual Learning for Image Recognition (He et al., 2015) — مقالهی اصلی ResNet؛ تکتک نمودارهای آن ارزش بررسی دقیق دارند.
- Very Deep Convolutional Networks (Simonyan & Zisserman, 2014) — مقالهی VGG؛ همچنان بهترین مرجع برای درک علت استفاده از فیلترهای 3x3.
- ImageNet Classification with Deep CNNs (Krizhevsky et al., 2012) — مقالهی AlexNet؛ اثری که به دوران استخراج دستی ویژگیها پایان داد.
- Going Deeper with Convolutions (Szegedy et al., 2014) — مقالهی Inception v1؛ ایدهی فیلترهای موازی که هنوز در ترنسفورمرهای بینایی به چشم میخورد.
