الرؤية الحاسوبية2017متوسط10 دقيقة قراءة
الشبكات الالتفافية ذات الاتصال الكثيف
Densely Connected Convolutional Networks
Huang, G. · Liu, Z. · Van Der Maaten, L. · Weinberger, K. Q. — CVPR
المشكلة
كلّما زاد عمق الشبكات الالتفافية — 50 ثم 100 ثم 150 طبقة — طالت المسافة التي تقطعها المعلومات والتدرُّجات. ResNet عالجت جزءاً من المشكلة بوصلات التخطّي، لكن آلية الجمع الحسابي فيها كانت تدمج السمات في قيمة واحدة، فتتلاشى السمات المبكرة تدريجياً. والأسوأ أن كل طبقة كانت مضطرة لإعادة تعلُّم أنماط استخلصتها طبقات سابقة بالفعل، ممّا يعني معاملات أكثر دون فائدة حقيقية. السؤال الذي طرحته هذه الورقة: هل نستطيع أن نمنح كل طبقة وصولاً مباشراً إلى كل ما أنتجته الطبقات السابقة، دون أن تضعف الإشارة في الطريق؟
الإسهام
شبكة DenseNet: بنية تربط كل طبقة بجميع الطبقات التي سبقتها عبر خرائط السمات على بُعد القنوات بدلاً من جمعها. داخل كل كتلة كثيفة، طبقة لها L سابقة تستقبل L مصفوفة مُلحَقة معاً. الفكرة الذكية أن كل طبقة لا تُضيف سوى k قناة جديدة ()، فتبقى الشبكة نحيفة رغم كثافة الاتصالات. بين الكتل تأتي طبقات انتقال تضغط القنوات وتُقلّص الأبعاد المكانية، كما تُستخدم طبقات عنق زجاجي (التفاف 1×1 قبل 3×3) لخفض التكلفة الحسابية. المحصلة: دقّة منافسة لأفضل النتائج على CIFAR وImageNet بمعاملات أقل بكثير من ResNet.
الأثر
حصدت DenseNet جائزة أفضل ورقة في CVPR 2017، وبرهنت أن الاستفادة القصوى من السمات الموجودة تتفوّق على مجرد تكديس مزيد من الطبقات. أثّر نمط الاتصال الكثيف في بنى لاحقة كـ EfficientNet ومتغيّرات DenseNet في التصوير الطبي وCondenseNet للأجهزة المحمولة. وترسّخ المبدأ الأساسي — «لا تُعِد تعلُّم ما تعرفه الشبكة بالفعل» — كقاعدة تصميمية في بناء البنى الفعّالة.
في الشبكات التقليدية، المعلومات تسير كـسباق تتابع: كل عدّاء () لا يُسلّم العصا إلا للعدّاء الذي يليه مباشرة. لو اكتشف العدّاء الأول شيئاً مهماً، فهذا الاكتشاف يجب أن يمرّ من يد إلى يد حتى يصل إلى خط النهاية — وقد يتشوّه في الطريق.
ResNet أضافت مساراً مختصراً: العصا تستطيع أن تقفز فوق عدّاء واحد. تحسُّن واضح، لكنها تبقى قفزة محدودة.
DenseNet غيّرت قواعد اللعبة تماماً بـسبّورة مشتركة: كل عدّاء يُدوّن ملاحظاته عليها، وأي عدّاء لاحق يقرأ كل شيء دُوِّن من البداية. لا شيء يضيع، ولا حاجة لاكتشاف ما اكتُشف سابقاً.
المشكلة: الشبكات العميقة تنسى السمات المبكرة
بحلول 2016، كانت ResNet قد أثبتت أن تُمكّن الشبكات من تجاوز 150 طبقة. لكن المشكلة أن هذه الوصلات تعتمد على الجمع الحسابي: مُخرج كل كتلة يُجمع مع مُدخلها. عملياً، هذا يعني أن الأصلية تنصهر في قيمة واحدة — فلا تستطيع الشبكة بعدها أن تُميّز ما أنتجته الطبقة الثالثة عمّا أنتجته الطبقة الثلاثون.
يترتّب على ذلك ثلاث مشكلات عملية:
-
ذوبان السمات المبكرة. الأولية كالحواف والأنسجة تنصهر في التمثيلات اللاحقة. فإن احتاجت طبقة عميقة إلى خريطة حواف خام، عليها أن تُعيد تعلُّمها من الإشارة المجموعة بدل الحصول عليها جاهزة.
-
هدر . كل طبقة تضطر لإعادة استخلاص سمات حسبتها طبقات سابقة بالفعل، فينتفخ حجم النموذج دون مكاسب حقيقية في الدقّة.
-
ضعف وصول . حتى مع وصلات التخطّي، تمرّ التدرُّجات عبر سلسلة طويلة من عمليات الجمع قبل أن تصل إلى الطبقات المبكرة، وكل عملية جمع قد تُضعف الإشارة.
الفكرة: اربط كل طبقة بكل طبقة
الفكرة المركزية في DenseNet بسيطة جداً: داخل كل كتلة كثيفة، كل طبقة تستقبل خرائط السمات من جميع الطبقات التي سبقتها، مُلحَقة على بُعد وليس مجموعة. لو كانت الكتلة تحتوي 5 طبقات وكل واحدة تُنتج k خريطة سمات (k هو «معدّل النمو»)، فالطبقة الخامسة ترى أمامها المُدخل الأصلي بجانبه 4×k قناة من الطبقات السابقة — مصفوفة بجوار بعضها، لا مُذابة في رقم واحد.
الصورة الذهنية الأوضح هنا هي ذاكرة جماعية تتّسع مع كل طبقة. الطبقة الأولى تكتب k صفحات جديدة. الثانية تقرأ كل ما سبق ثم تُضيف k صفحات من عندها. عند الطبقة L، تحتوي الذاكرة على المُدخل الأصلي زائد L×k صفحة — وكل طبقة تستطيع تصفّح أي صفحة تحتاجها مباشرة.
وهنا النقطة الجوهرية: الإلحاق يحفظ هوية كل إشارة. حين تجمع إشارتين حسابياً تفقد القدرة على التمييز بينهما. أمّا حين تُلحقهما، فكل إشارة تحتفظ بقنواتها المستقلة — وهذا يسمح للشبكة بأن تتعلّم توجيه المعلومات من أي طبقة سابقة إلى أي طبقة لاحقة بلا خسارة.
داخل الكتلة الكثيفة
كل طبقة داخل تُطبّق دالة مركّبة على المُدخلات المُلحَقة من جميع الطبقات السابقة. هذه الدالة عادةً تتكوّن من ثم ثم 3×3. كل طبقة تُنتج k خريطة سمات فقط، حيث k هو معدّل النمو. واللافت أن قيماً صغيرة لـ k (مثل 12 أو 32) تُعطي نتائج ممتازة، والسبب بديهي: كل طبقة تملك وصولاً مباشراً إلى كل ما أنتجته الطبقات السابقة، فلا حاجة لقنوات كثيرة لإعادة إنتاج ما هو متاح أصلاً.
معدّل النمو — إبقاء الشبكة نحيفة
الملاحظة الذكية هنا: ما دامت كل طبقة تصل إلى جميع السمات السابقة مباشرة، فلا حاجة لأن تُنتج عدداً كبيراً من خرائط السمات الجديدة. يكفيها إضافة عدد صغير k من القنوات الجديدة — وهذا ما يُسمى معدّل النمو. في الممارسة، DenseNet تستخدم عادةً k = 12 أو k = 32، وهي قيم أصغر بكثير من 64 أو 256 المعتادة في ResNet.
حسابياً، بعد L طبقة في كتلة كثيفة تبدأ بـ قناة، يصبح إجمالي القنوات . لاحظ أن النمو خطّي وليس أُسّياً، وهذا ما يُبقي الشبكة مضغوطة. مع k = 12 و40 طبقة مثلاً، الطبقة الأخيرة تستقبل قناة فقط — والجميل أن معظم المعلومات التي تحتاجها موجودة فعلاً في تلك القنوات القادمة من طبقات سابقة.
طبقات الانتقال والعنق الزجاجي — الضغط الذكي
داخل الكتلة الكثيفة، جميع خرائط السمات تحتفظ بالأبعاد المكانية نفسها — لأن الإلحاق يتطلب تطابق الارتفاع والعرض. لكن بين كتلة وأخرى، لا بدّ من ضغط المعلومات وتصغير الأبعاد. هنا يأتي دور طبقات الانتقال التي تؤدي مهمتين:
-
ضغط القنوات: التفاف 1×1 يُقلّص عدد القنوات بمعامل ضغط θ (عادةً 0.5، أي يختزلها إلى النصف). بدون هذه الخطوة، ستتراكم القنوات وتتضخّم الذاكرة بسرعة.
-
تصغير مكاني: 2×2 يُنصّف الأبعاد المكانية، كما هو معتاد في الشبكات الالتفافية.
أمّا داخل الكتلة نفسها، فهناك حيلة إضافية تُسمّى : قبل كل التفاف 3×3، يُدرَج التفاف 1×1 يضغط المُدخل المُلحَق إلى 4k قناة. التسلسل الكامل يصبح: تسوية دُفعات ← ReLU ← التفاف 1×1 (إلى 4k) ← تسوية دُفعات ← ReLU ← التفاف 3×3 (إلى k). هذا المتغيّر يُعرف بـ DenseNet-B، وحين يُجمع مع ضغط طبقات الانتقال نحصل على DenseNet-BC.
لماذا ينجح الاتصال الكثيف
الاتصال الكثيف يمنح DenseNet أربع مزايا مترابطة تُفسّر نجاحها:
-
. كل طبقة تصل مباشرة إلى سمات أي طبقة سبقتها، فلا تُضطر الشبكة لإعادة تعلُّم الأنماط الأساسية في العمق. والمثير أن التجارب أكّدت ذلك عملياً: الطبقات المتأخرة تعتمد بشدّة على السمات المبكرة — أي أن ليست مجرد ميزة نظرية، الشبكة تستغلّها فعلاً.
-
تدفّق أقوى لـالتدرُّجات. كل طبقة تملك مساراً مباشراً يربطها بـ. الأمر أشبه بأن تكون لكل طبقة قناة اتصال خاصة مع إشارة الخطأ، بدل أن تنتظر وصول الرسالة عبر سلسلة من الوسطاء.
-
إشراف عميق ضمني. بفضل المسارات القصيرة المتعددة بين كل طبقة والخسارة، تتصرّف الشبكة وكأنها تحتوي بداخلها مجموعة من الشبكات القصيرة تتعلّم جميعها في آنٍ واحد.
-
كفاءة المعاملات. ما دامت السمات تُعاد استخدامها بدل إعادة حسابها، تحقّق الشبكة الدقّة ذاتها بمعاملات أقل بكثير. مثال صارخ: DenseNet-BC من 100 طبقة تتفوّق على ResNet من 1001 طبقة مع توفير 90% من المعاملات.
تجميع القطع معاً
بنية DenseNet الكاملة على ImageNet تسير كالتالي: تبدأ بـالتفاف 7×7 أوّلي يليه 3×3، ثم تأتي 4 كتل كثيفة يفصل بينها 3 طبقات انتقال، وتنتهي بـتجميع متوسط شامل ومصنِّف .
المتغيّرات الأكثر شيوعاً هي DenseNet-121 و169 و201 و264، والفرق بينها هو عدد الطبقات في كل كتلة كثيفة. جميعها تعمل بمعدّل نمو k = 32 ومعامل ضغط θ = 0.5. ولتوضيح مدى الكفاءة: DenseNet-264 — أعمق هذه المتغيّرات — تحتوي 15.3 مليون معامل فقط، بينما ResNet-152 تحتاج إلى 60.2 مليون معامل لتحقيق دقّة مماثلة.
الفكرة ذاتها في شيفرة برمجية
مبسَّط لإظهار الفكرة — ليس التنفيذ الحقيقي.
import torch
import torch.nn as nn
class DenseLayer(nn.Module):
"""طبقة واحدة داخل كتلة كثيفة: BN-ReLU-1x1-BN-ReLU-3x3."""
def __init__(self, in_channels, growth_rate):
super().__init__()
# عنق زجاجي: اضغط إلى 4k قناة أولاً
self.bn1 = nn.BatchNorm2d(in_channels)
self.conv1 = nn.Conv2d(in_channels, 4 * growth_rate, 1, bias=False)
# ثم أنتج k خريطة سمات جديدة
self.bn2 = nn.BatchNorm2d(4 * growth_rate)
self.conv2 = nn.Conv2d(4 * growth_rate, growth_rate, 3, padding=1, bias=False)
self.relu = nn.ReLU(inplace=True)
def forward(self, prev_features):
# prev_features: قائمة مصفوفات من كل الطبقات السابقة
x = torch.cat(prev_features, dim=1) # إلحاق وليس جمع!
x = self.conv1(self.relu(self.bn1(x)))
x = self.conv2(self.relu(self.bn2(x)))
return x # k قناة جديدة
class DenseBlock(nn.Module):
def __init__(self, n_layers, in_channels, growth_rate):
super().__init__()
self.layers = nn.ModuleList()
for i in range(n_layers):
self.layers.append(DenseLayer(in_channels + i * growth_rate, growth_rate))
def forward(self, x):
features = [x] # ابدأ بالمُدخل الأولي
for layer in self.layers:
new = layer(features) # كل طبقة ترى جميع السمات السابقة
features.append(new) # أضف مُخرجها إلى الذاكرة المشتركة
return torch.cat(features, dim=1) # أعِد الإلحاق الكامل
class Transition(nn.Module):
"""بين الكتل الكثيفة: اضغط القنوات وقلّص الأبعاد المكانية."""
def __init__(self, in_channels, compression=0.5):
super().__init__()
out_channels = int(in_channels * compression)
self.bn = nn.BatchNorm2d(in_channels)
self.conv = nn.Conv2d(in_channels, out_channels, 1, bias=False) # ضغط θ
self.pool = nn.AvgPool2d(2, stride=2) # نصّف الأبعاد المكانية
def forward(self, x):
return self.pool(self.conv(torch.relu(self.bn(x))))كفاءة المعاملات — دقّة أعلى بمعاملات أقل
النتيجة الأكثر لفتاً للانتباه في DenseNet هي كفاءتها في استخدام المعاملات. على CIFAR-10 مثلاً، DenseNet-BC من 100 طبقة مع k = 12 تحقّق نسبة خطأ 4.51% بـ 0.8 مليون معامل فقط — أداء يُضاهي ما تحققه شبكة ResNet بعشرة أضعاف هذا العدد من المعاملات.
على ImageNet، DenseNet-201 بـ 20 مليون معامل تُنافس ResNet-101 بـ 44.5 مليون معامل. هذا التقليص إلى النصف مصدره بالكامل إعادة استخدام السمات: حين تصل كل طبقة مباشرة إلى كل ما أنتجته الطبقات السابقة، تنتفي الحاجة إلى قنوات عريضة لإعادة إنتاج تمثيلات موجودة أصلاً.
لماذا أهمّ الأمر
أثر DenseNet يمتد في عدة اتجاهات. EfficientNet بنت على فكرة أن نمط الاتصالات يُحدث فرقاً، فطبّقت تحجيماً منهجياً للعمق والعرض والدقّة معاً. في التصوير الطبي، أصبحت بنى DenseNet خياراً شائعاً لأن كفاءتها في استخدام المعاملات تحدّ من على مجموعات البيانات الصغيرة — وهي مشكلة مزمنة في التطبيقات السريرية. كما أثبتت CondenseNet أن الالتفافات الزمرية المُتعلَّمة تستطيع تقليم الاتصالات الكثيفة غير الضرورية، فتصير بنى DenseNet سريعة بما يكفي للعمل على الأجهزة المحمولة.
الدرس الأعمق هنا: في ، كثرة الاتصالات قد تعني معاملات أقل لا أكثر. حين تتدفق المعلومات بحرية بين الطبقات، لا تحتاج كل طبقة إلى إعادة اختراع العجلة. وهذا ما أثبتته DenseNet: الكفاءة والدقّة ليستا قوّتين متعارضتين — بل يمكنهما أن تُعزّزا بعضهما.
2015
ResNet — وصلات التخطّي تُمكّن 152 طبقة
قدّم He وفريقه وصلات متبقية تنقل المُدخل مباشرة إلى مُخرج كل كتلة، فتتدفق التدرُّجات عبر مسار الهوية دون عوائق. هذا مكّن من بناء شبكات أعمق بكثير مما كان ممكناً سابقاً، وفازت ResNet بمسابقة ImageNet 2015 بفارق واضح.
2016
العمق العشوائي — إسقاط طبقات عشوائياً
اكتشف Huang وفريقه أن حذف طبقات عشوائياً أثناء التدريب يُحسّن أداء ResNet. الاستنتاج المهم: ليست كل الطبقات تُسهم بالقدر نفسه، وهذا مهّد الطريق لفكرة DenseNet بأن إعادة استخدام السمات أجدى من مجرد تكديس العمق.
2017
DenseNet — الاتصالات الكثيفة وإعادة استخدام السمات
قدّم Huang وLiu وVan Der Maaten وWeinberger شبكة DenseNet في CVPR 2017 وحصدت جائزة أفضل ورقة. الفكرة: ربط كل طبقة بجميع سابقاتها عبر الإلحاق بدل الجمع، ممّا حقّق دقّة عالية بمعاملات أقل بكثير.
2018
CondenseNet — تقليم الاتصالات الكثيفة للأجهزة المحمولة
أثبت Huang وفريقه أن الالتفافات الزمرية المُتعلَّمة قادرة على تقليم الاتصالات غير المفيدة في DenseNet تلقائياً، فأصبحت البنية سريعة بما يكفي للاستدلال اللحظي على الهواتف المحمولة.
2019
EfficientNet — التحجيم المُركَّب
طوّر Tan وLe منهجية لتحجيم العمق والعرض ودقة الصورة معاً بشكل متوازن، مستفيدَين من دروس DenseNet وبنى فعّالة أخرى في أن طريقة تصميم البنية لا تقل أهمية عن حجمها.
2020
DenseNet في التصوير الطبي
انتشرت بنى DenseNet في تحليل الصور الطبية — الأشعة السينية والتصوير المقطعي وتحليل الأنسجة — لأن كفاءتها في استخدام المعاملات تُعدّ ميزة حاسمة حين تكون البيانات المتاحة محدودة.
المرجعHuang, Liu, Van Der Maaten, Weinberger. Densely Connected Convolutional Networks. CVPR, 2017.
مصطلحات هذه الورقة
- الاتصالات الكثيفةDense Connections
- إعادة استخدام السماتFeature Reuse
- معدّل النموGrowth Rate
- الكتلة الكثيفةDense Block
- طبقة الانتقالTransition Layer
- عنق الزجاجةBottleneck
- خريطة السماتFeature Map
- القناة البنيويةChannel
- الإلحاقConcatenation
- الوصلة التجاوزيةResidual Connection
- تسوية الدفعات الحسابيةBatch Normalization