الوحدة 9 — التعلّم بالنقل مع torchvision
بلغنا في الوحدة الثامنة نموذجًا يعمل من طرف إلى طرف على Fashion-MNIST،
مبنيًّا من الصفر. الحقيقة أنّ التدريب من الصفر نادرًا ما يكون
القرار الصحيح في الرؤية الحاسوبية اليوم. إعادة استعمال شبكة
مُدرَّبة مسبقًا على ImageNet ثم ضبطها على مهمّتك تُعطي نتائج أفضل
بكثير من الصفر، في وقت أقلّ. هذه الوحدة تشرح كيف نفعل ذلك في PyTorch
عبر torchvision.models.
لماذا يعمل النقل: الطبقات الأولى عامّة
شبكة تلافيفية عميقة تُدرَّب على ImageNet تتعلّم أوّلاً كشف الحواف والزوايا، ثم القوامات والألوان، ثم أجزاء الأشياء، ثم الأشياء الكاملة. الطبقات الأولى لا تختصّ بأصناف ImageNet: كاشف الحواف مفيد لأيّ صورة، بما فيها صور الملاب س في Fashion-MNIST. الطبقات الأخيرة وحدها هي المُتخصّصة، وهي التي نستبدل.
تحميل نموذج مُدرَّب مسبقًا
torchvision.models يوفّر عشرات المعماريّات مع أوزان جاهزة:
import torch
from torchvision import models
# الطريقة الحديثة (منذ torchvision 0.13)
poids = models.ResNet18_Weights.IMAGENET1K_V1
modele = models.resnet18(weights=poids)
الاستدعاء يُنزّل الأوزان أوّل مرّة (نحو 45 ميغابايت لـResNet18) ويحفظها في مجلّد داخليّ. الاستدعاءات اللاحقة تقرأ من الذاكرة المحلية. لا حاجة إلى تحضير أيّ ملفّ بنفسك.
استبدال الرأس
ResNet18 مُدرَّب على 1000 صنف؛ نريده على 10 أصناف. نستبدل الطبقة
الأخيرة:
import torch.nn as nn
# الطبقة الأخيرة تُسمّى fc في ResNet
n_car = modele.fc.in_features # 512 في ResNet18
modele.fc = nn.Linear(n_car, 10) # رأس جديد لعشرة أصناف
نلاحظ ثلاث نقاط. أوّلًا، حفظ in_features قبل الاستبدال ضروريّ
لأنّ الطبقة القديمة تختفي في السطر التالي. ثانيًا، الرأس الجديد
يُهيَّأ عشوائيًّا: أوزانه لم تُدرَّب بعد. ثالثًا، اسم الطبقة
الأخيرة يختلف حسب المعمارية: fc في ResNet، classifier في VGG،
heads.head في Vision Transformer. لا اسم موحّد.