Sistem deteksi dunia nyata datang dalam dua rumpun: detektor dua tahap mengusulkan kandidat wilayah lalu mengklasifikasikannya, sedangkan detektor satu tahap memetakan gambar langsung ke prediksi — perbandingan keduanya dibahas pada chapter Object Detection . Pada gambar sintetis 32x32 dengan tepat satu objek, kita memilih desain satu tahap paling sederhana: satu CNN dengan dua kepala keluaran, sehingga satu forward pass menghasilkan kelas dan kotak sekaligus.
Arsitektur Dua Kepala #
Class DetektorMini di src/model.py membagi dirinya menjadi tubuh bersama dan dua kepala:
class DetektorMini(nn.Module):
def __init__(self):
super().__init__()
self.tubuh = nn.Sequential(
nn.Conv2d(1, 8, 3, padding=1), nn.ReLU(), nn.MaxPool2d(2),
nn.Conv2d(8, 16, 3, padding=1), nn.ReLU(), nn.MaxPool2d(2),
nn.Conv2d(16, 32, 3, padding=1), nn.ReLU(),
nn.Flatten(),
)
self.kepala_kelas = nn.Linear(32 * 8 * 8, 3)
self.kepala_kotak = nn.Linear(32 * 8 * 8, 4)
def forward(self, x: torch.Tensor):
fitur = self.tubuh(x)
return self.kepala_kelas(fitur), torch.sigmoid(self.kepala_kotak(fitur))Tiga keputusan pada arsitektur ini perlu dibedah:
- Tubuh bersama: tiga blok konvolusi + ReLU mengekstrak fitur spasial sekali untuk dua tugas — pola “blok terang di mana” berguna bagi klasifikasi maupun regresi kotak, sehingga berbagi tubuh menghemat parameter dan mempercepat belajar.
padding=1dengan duaMaxPool2d(2): konvolusi menjaga ukuran, pooling memangkalinya — 32 menjadi 16 menjadi 8, sehingga peta fitur akhir berukuran 8x8 dan setiap sel mewakili wilayah 4x4 piksel; struktur konvolusi-pooling ini dibahas pada chapter Pooling Layer .torch.sigmoidhanya di kepala kotak: empat angka kotak dinormalisasi ke rentang 0..1 terhadap ukuran gambar, sehingga jaringan sulit memprediksi koordinat di luar kanvas; kepala kelas memakai logits mentah karena cross-entropy sudah menyertakan softmax di dalamnya.
Menjalankan python3 src/model.py mencetak anatomi lengkap model sebelum dilatih:
== anatomi DetektorMini ==
conv1 + bias : 80
conv2 + bias : 1168
conv3 + bias : 4640
kepala_kelas : 6147
kepala_kotak : 8196
total parameter : 20231
bentuk keluaran logits : (2, 3)
bentuk keluaran kotak : (2, 4)
rentang kotak (sigmoid): [0.491, 0.538]Model hanya menampung 20231 parameter — tubuh konvolusi 5888, dua kepala menyisakan 14343 karena nn.Linear membaca seluruh peta fitur 2048-dimensi. Keluaran ujung ke ujung berbentuk pasangan (logits (B,3), kotak (B,4)), dan rentang sigmoid yang sempit (0.491-0.538) pada model acak menegaskan bahwa kepala kotak memang dimulai dari “tebakan tengah gambar”.
Loss Gabungan Dua Tugas #
Dua kepala berarti dua loss yang harus digabung:
LAMBDA_KOTAK = 20.0
def loss_gabungan(logit_kelas, kotak_pred, kelas_target, kotak_target):
"""Loss = CE kelas + lambda * MSE kotak ternormalisasi."""
ce = nn.functional.cross_entropy(logit_kelas, kelas_target)
mse = nn.functional.mse_loss(kotak_pred, kotak_target)
return ce + LAMBDA_KOTAK * mse, ce.item(), mse.item()Cross-entropy menghukum salah kelas; MSE menghukum kotak yang meleset. Faktor LAMBDA_KOTAK = 20.0 menyeimbangkan keduanya: MSE pada koordinat ternormalisasi bernilai kecil (orde 0.01), sehingga tanpa pembobotan loss kotak tenggelam dan model belajar klasifikasi saja sambil mengabaikan posisi — masalah penyeimbangan loss multi-tugas yang juga muncul pada chapter Loss dan Optimizer
.
Fungsi prediksi menutup modul ini untuk inferensi: model.eval() menonaktifkan mode latih, softmax mengubah logits menjadi peluang, dan kotak ternormalisasi dikalikan 32 kembali menjadi satuan piksel.
Sebelum melanjutkan, mari kita jujur menandai tiga penyederhanaan desain ini terhadap detektor dunia nyata. Setiap gambar di proyek kita memuat tepat satu objek, jadi dua kepala cukup — detektor nyata harus memprediksi banyak kotak sekaligus, biasanya lewat kotak jangkar pada tiap sel grid, lalu menyaring tumpang-tindih dengan non-maximum suppression. Kepala kotak kita langsung meregresi empat angka untuk seluruh gambar, bukan offset terhadap jangkar per sel. Terakhir, ambang keyakinan kita baru muncul di tahap evaluasi; detektor nyata memakainya saat inferensi untuk membuang deteksi lemah. Ketiga mekanisme itu dibahas pada chapter Object Detection — memahaminya setelah menuntaskan versi mini akan terasa jauh lebih mudah karena pertanyaan dasarnya sudah pernah Anda jawab sendiri.
Arsitektur dan loss siap, tinggal menghidupkannya dengan data. Bagian berikutnya menjalankan pelatihan 60 epoch lalu membaca hasilnya lewat IoU dan Average Precision.