الدرس 8 من 8
الـ Transfer Learning
إزاي تعمل موديل صور ممتاز بمية صورة بس.
الفكرة
لو بتتعلم تسوق عربية نقل وانت أصلاً بتسوق ملاكي، مش هتبدأ من الصفر: انت عارف الدريكسيون والفرامل والإشارات، ومحتاج تتعلم الفرق بس. الـ Transfer Learning نفس الكلام: موديل اتدرب على ملايين الصور (ImageNet) واتعلم يشوف حواف وأشكال وأجزاء، وانت بتعلّمه بس آخر خطوة الخاصة بمشكلتك.
✓ Transfer Learningمئات الصور، دقايق تدريب على GPU واحد، ودقة عالية.
✗ من الصفرملايين الصور، أيام أو أسابيع تدريب، وأجهزة غالية.
حمّل موديل جاهز وجهّزه
هنعمل موديل يفرق بين ٣ أكلات مصرية: كشري، وطعمية، وملوخية. هناخد ResNet18 المتدرب، نجمّد كل طبقاته، ونبدل آخر طبقة بطبقة جديدة فيها ٣ مخرجات:
import torch from torch import nn from torchvision.models import resnet18, ResNet18_Weights model = resnet18(weights=ResNet18_Weights.DEFAULT) # downloads pretrained weights for param in model.parameters(): # freeze everything it already learned param.requires_grad = False print("original last layer:", model.fc) model.fc = nn.Linear(model.fc.in_features, 3) # new head: koshari / falafel / molokhia total = sum(p.numel() for p in model.parameters()) trainable = sum(p.numel() for p in model.parameters() if p.requires_grad) print(f"total parameters: {total:,}") print(f"trainable parameters: {trainable:,}")
من أكتر من ١١ مليون وزن، هنتدرب على ١٥٣٩ بس. عشان كده التدريب سريع ومحتاج صور قليلة.
جهّز الصور في فولدرات
food_data/
train/
koshari/ img001.jpg, img002.jpg, ...
falafel/ ...
molokhia/ ...
val/
koshari/ ...
falafel/ ...
molokhia/ ...
# folder names become the class names automaticallyالتدريب
import torch from torch import nn from torchvision import datasets, transforms from torchvision.models import resnet18, ResNet18_Weights from torch.utils.data import DataLoader device = "cuda" if torch.cuda.is_available() else "cpu" weights = ResNet18_Weights.DEFAULT train_tf = transforms.Compose([ transforms.RandomResizedCrop(224), # data augmentation: transforms.RandomHorizontalFlip(), # new variations every epoch weights.transforms(), # resize + normalize like ImageNet ]) train_ds = datasets.ImageFolder("food_data/train", transform=train_tf) val_ds = datasets.ImageFolder("food_data/val", transform=weights.transforms()) train_dl = DataLoader(train_ds, batch_size=32, shuffle=True) val_dl = DataLoader(val_ds, batch_size=32) model = resnet18(weights=weights) for p in model.parameters(): p.requires_grad = False model.fc = nn.Linear(model.fc.in_features, len(train_ds.classes)) model = model.to(device) opt = torch.optim.Adam(model.fc.parameters(), lr=1e-3) # only the new head loss_fn = nn.CrossEntropyLoss() for epoch in range(5): model.train() for xb, yb in train_dl: xb, yb = xb.to(device), yb.to(device) opt.zero_grad() loss_fn(model(xb), yb).backward() opt.step() model.eval() correct = 0 with torch.no_grad(): for xb, yb in val_dl: preds = model(xb.to(device)).argmax(1).cpu() correct += (preds == yb).sum().item() print(f"epoch {epoch}: val accuracy = {correct / len(val_ds):.1%}")
data augmentation بنعمل نسخ معدلة من الصور (قص، قلب، إضاءة) فالموديل يشوف تنوع أكتر من غير صور جديدة.freezing إنك توقف تعلم الطبقات القديمة عشان متبوظش اللي اتعلمته.fine-tuning بعد ما الـ head الجديدة تتعلم، ممكن تفك آخر كام طبقة وتدربهم بـ learning rate صغير جداً.💡 منين تجيب موديلات جاهزة؟
torchvision.models فيها أشهر موديلات الصور. ومكتبة timm فيها مئات. وHugging Face فيه آلاف الموديلات لكل حاجة: صور، ونصوص، وصوت، وهتعيش فيه في المرحلة الجاية.🚀 مشروعكصوّر ٥٠ صورة لكل نوع من ٣ حاجات حواليك (أنواع نبات، ماركات عربيات، أكلات)، وطبّق الكود ده في Colab. في أقل من ساعة هيبقى عندك موديل صور حقيقي عملته بنفسك، وده مشروع ممتاز للـ portfolio.