Topik ini membahas model zoo torchvision, yaitu kumpulan arsitektur klasifikasi citra yang bobotnya sudah dilatih sebelumnya pada dataset besar dan siap dimuat dalam beberapa baris kode. Bahasannya mencakup cara menelusuri isi model zoo, memilih varian bobot melalui API weights, memuat ResNet18 dengan bobot ImageNet, serta membaca transformasi praproses resmi yang menyertai setiap varian bobot. Setelah topik ini, model berkualitas tinggi dapat dimuat dan dijalankan pada CPU tanpa satu pun langkah pelatihan.
Model zoo torchvision.models#
Modul torchvision.models berisi fungsi pembuat arsitektur, mulai dari alexnet dan keluarga VGG yang klasik hingga ResNet, DenseNet, MobileNet, EfficientNet, dan Vision Transformer yang lebih modern. Setiap arsitektur memiliki satu fungsi pembuat yang dinamai menurut arsitekturnya, misalnya resnet18() dan mobilenet_v2(). Seluruh fungsi tersebut mengembalikan objek nn.Module, sehingga peralatan yang digunakan pada modul Membangun Model, seperti named_parameters(), eval(), dan pemanggilan forward, berlaku apa adanya.
Isi model zoo dapat ditelusuri tanpa memuat model apa pun melalui fungsi list_models():
from torchvision.models import list_models
nama = list_models()
print("jumlah model:", len(nama))
print("contoh nama :", nama[:8])jumlah model: 121
contoh nama : ['alexnet', 'convnext_base', 'convnext_large', 'convnext_small', 'convnext_tiny', 'deeplabv3_mobilenet_v3_large', 'deeplabv3_resnet101', 'deeplabv3_resnet50']Keluaran menunjukkan 121 fungsi pembuat yang terdaftar dan diurutkan menurut abjad. Nama pada daftar itu sekaligus menjadi nama fungsinya di torchvision.models, sehingga densenet121 pada daftar dipanggil sebagai torchvision.models.densenet121(). Sebagian nama melayani tugas selain klasifikasi, misalnya deeplabv3_resnet50 untuk segmentasi semantik, tetapi fokus topik ini adalah arsitektur klasifikasi citra.
Memuat bobot pretrained dengan enum Weights#
Memanggil fungsi pembuat tanpa argumen menghasilkan arsitektur lengkap dengan bobot acak, yakni bobot yang belum dipelajari dari data apa pun. Untuk memuat hasil pelatihan, fungsi pembuat menerima argumen weights berisi anggota enum Weights. Pada ResNet18, enum-nya bernama ResNet18_Weights dan anggotanya bernama IMAGENET1K_V1, yang menandai bobot hasil pelatihan ResNet18 pada dataset ImageNet-1K dengan resep pelatihan versi pertama. Bentuk enum ini dipilih karena satu arsitektur dapat memiliki beberapa varian bobot dari resep atau dataset yang berbeda, dan setiap varian membawa metadata miliknya sendiri.
Isi enum tersebut dapat diperiksa langsung:
from torchvision.models import ResNet18_Weights
print(list(ResNet18_Weights))
bobot = ResNet18_Weights.IMAGENET1K_V1
print(bobot.meta["_metrics"])
print(bobot.meta["num_params"])[ResNet18_Weights.IMAGENET1K_V1]
{'ImageNet-1K': {'acc@1': 69.758, 'acc@5': 89.078}}
11689512Keluaran memperlihatkan tiga informasi. Enum ResNet18_Weights saat ini hanya memiliki satu anggota, yaitu IMAGENET1K_V1. Metadata metriknya mencatat akurasi atas satu (acc@1) sebesar 69.758% dan akurasi atas lima (acc@5) sebesar 89.078% pada ImageNet-1K. Terakhir, jumlah parameternya adalah 11689512.
Arsitektur yang lebih besar dapat memiliki beberapa varian bobot sekaligus, sehingga kebiasaan memeriksa isi enum sebelum memuat selalu berguna. Sebagai catatan sejarah, argumen pretrained=True dari versi lama torchvision sudah tidak digunakan lagi sejak versi 0.13 dan digantikan sepenuhnya oleh argumen weights. Argumen lama itu masih diterima dengan peringatan deprecated, sehingga tidak ada alasan menggunakannya pada kode baru.
Skrip berikut memuat ResNet18 beserta bobot pretrained-nya, lalu menjalankan satu forward untuk memastikan semuanya utuh:
import torch
from torchvision.models import resnet18, ResNet18_Weights
model = resnet18(weights=ResNet18_Weights.IMAGENET1K_V1)
print("tipe model :", type(model).__name__)
print("head bawaan :", model.fc)
print("parameter :", sum(p.numel() for p in model.parameters()))
x = torch.zeros(1, 3, 224, 224) # satu citra sintetis 224x224
with torch.no_grad():
y = model(x)
print("keluaran :", tuple(y.shape))tipe model : ResNet
head bawaan : Linear(in_features=512, out_features=1000, bias=True)
parameter : 11689512
keluaran : (1, 1000)Pada pemanggilan pertama, bobot sekitar 45 MB diunduh dari server resmi PyTorch, sedangkan pemanggilan berikutnya cukup membaca cache tanpa unduhan. Head bawaan berupa Linear(512, 1000), dan forward pada citra 224x224 menghasilkan 1000 logits sesuai jumlah kelas ImageNet-1K. Ukuran masukan 224x224 bukan pilihan sembarang, melainkan tuntutan bobot ini yang dijelaskan pada bagian berikutnya.
Diagram berikut merangkum kedua cara memuat model, yaitu dengan bobot acak dan dengan bobot pretrained:
Transformasi yang menyertai bobot#
Model pretrained hanya memberikan hasil yang baik apabila citra masukannya dipraproses persis seperti saat bobot itu dilatih. Menyusun praproses itu dari ingatan rawan salah, sehingga setiap anggota enum bobot menyediakan method transforms() yang mengembalikan pipeline praproses resmi milik varian tersebut. Pipeline ini berupa objek transformasi biasa, sehingga dapat diserahkan langsung ke parameter transform milik dataset sebagaimana dibahas pada modul Pemuatan Data.
Method itu dapat dipanggil dan dicetak untuk melihat isinya:
from torchvision.models import ResNet18_Weights
print(ResNet18_Weights.IMAGENET1K_V1.transforms())ImageClassification(
crop_size=[224]
resize_size=[256]
mean=[0.485, 0.456, 0.406]
std=[0.229, 0.224, 0.225]
interpolation=InterpolationMode.BILINEAR
)Keluaran menjelaskan seluruh tuntutan masukan bobot ini. Citra terlebih dahulu diperbesar agar sisi terpendeknya berukuran 256 piksel, kemudian dipotong di tengah menjadi 224x224, dan itulah asal ukuran masukan pada skrip sebelumnya. Setelah itu citra diubah menjadi tensor dan dinormalisasi dengan mean serta simpangan baku statistik ImageNet, yaitu nilai yang sama dengan yang diperkenalkan pada topik Transformasi. Interpolasi bilinear digunakan pada perubahan ukurannya.
Keluaran model dan batasannya#
ResNet18 pretrained menghasilkan 1000 logits, satu untuk setiap kelas ImageNet-1K, dan daftar lengkap kelasnya tersimpan pada metadata bobot:
from torchvision.models import ResNet18_Weights
kategori = ResNet18_Weights.IMAGENET1K_V1.meta["categories"]
print(len(kategori), "kelas")
print(kategori[:8])1000 kelas
['tench', 'goldfish', 'great white shark', 'tiger shark', 'hammerhead', 'electric ray', 'stingray', 'cock']Nilai keluaran tersebut adalah logits mentah, bukan probabilitas, sehingga nilainya dapat negatif dan jumlahnya bukan satu. Untuk memperoleh label prediksi, ambil indeks terbesar dengan argmax, sedangkan probabilitas per kelas memerlukan softmax yang dipanggil terpisah. Satu hal lagi yang mudah terlewat: fungsi pembuat mengembalikan model dalam mode train, sehingga inferensi wajib didahului model.eval() agar batch normalization menggunakan statistik berjalannya.
Head yang menunjuk 1000 kelas ImageNet juga menegaskan batas model ini. Tugas baru yang hanya memiliki beberapa kelas, misalnya empat jenis daun, tidak terwakili oleh head bawaan, sehingga head harus diganti dan strategi pelatihannya disesuaikan. Cara mengganti head dan membekukan backbone merupakan inti topik Pembekuan dan penggantian head.
Kesalahan umum#
Lupa memanggil model.eval() sebelum inferensi. Model keluar dari fungsi pembuat dalam mode train, sehingga batch normalization menghitung statistik dari batch yang sedang diproses alih-alih menggunakan statistik berjalan. Keluaran untuk citra yang sama pun berubah-ubah mengikuti isi batch. Perbaikannya adalah memanggil model.eval() sebelum perulangan inferensi, satu panggilan untuk seluruh model.
Menganggap keluaran model sebagai probabilitas. Model mengembalikan logits mentah, sehingga membandingkan nilainya langsung dengan ambang probabilitas 0 sampai 1 keliru tanpa pesan error. Perbaikannya adalah mengambil label dengan argmax pada dimensi kelas, atau menerapkan softmax secara eksplisit terlebih dahulu apabila nilai probabilitas memang diperlukan.
Ringkasan#
torchvision.modelsmenyediakan 121 fungsi pembuat arsitektur yang semuanya mengembalikannn.Modulebiasa.- Bobot pretrained dimuat melalui enum, misalnya
ResNet18_Weights.IMAGENET1K_V1, dan setiap varian membawa metadata resep, metrik, jumlah parameter, serta transformasi. - Method
weights.transforms()mengembalikan pipeline praproses resmi berupa resize 256, center crop 224, dan normalisasi ImageNet. - ResNet18 pretrained menghasilkan 1000 logits ImageNet-1K, dan inferensinya wajib didahului
model.eval().
Referensi#
- torchvision.models — PyTorch — Dokumentasi model zoo, daftar bobot, dan cara menginisialisasi model pretrained.
- torchvision.models.resnet18 — PyTorch
— Dokumentasi fungsi pembuat ResNet18 beserta enum
ResNet18_Weights. - Transfer Learning for Computer Vision Tutorial — PyTorch — Tutorial resmi yang memuat ResNet18 pretrained dan menyiapkan pipeline transformasinya.