Notebook’ta iyi skor alan bir model ürün değildir. SUAS için YOLOv11m dedektörünü mAP50 = 0,904 ve mAP50-95 = 0,691’e kadar eğittik ve uçak onu çalıştıramadığı sürece bunların hiçbir önemi yok. Yarışma masaüstü GPU’da olmuyor. Gövdeye vidalanmış, güç bütçesini uçaktaki her şeyle paylaşan bir Jetson üzerinde oluyor.
best.pt dosyasından uçan bir sisteme gitmek başlı başına bir mühendislik işi.
Bu yazı o iş.

Çizim bana ait, çubuklar ölçüm değil temsili. Mesele şekil: doğruluk yerinde dururken hız tırmanıyor.
Checkpoint bitiş çizgisi değil
PyTorch bir eğitim çatısı. Gittiği her yere dinamik graf, autograd mekanizması ve bir Python yorumlayıcısı taşıyor. İş istasyonunda bu yükü hiç fark etmezsin. Sabit termal zarfı olan gömülü bir kartta anında fark edersin: aynı model, aynı ağırlıklar ve bütün sistemi anlamsız kılan bir kare hızı.
Ağırlıklar, sahaya alma probleminin belki üçte biri. Gerisi o ağırlıkların nasıl çalıştırıldığı.
Bunu ilk kez yaşayan herkesin tepkisi aynı: suçu karta atmak. Kart suçlu değil. Aynı silikon, aynı ağırlıklarla çok daha hızlı koşabiliyor; sadece eğitim çatısının konforunu sahaya taşımaman gerekiyor. Eğitimde işine yarayan esnekliğin her parçası, çıkarımda ödediğin bir vergi.
TensorRT gerçekte ne yapıyor
TensorRT ağını alıp tek bir spesifik GPU için derliyor. Önemli olan üç şey oluyor.
Katmanları birleştiriyor: bir konvolüsyon, batch norm’u ve aktivasyonu, belleğe üç ayrı gidiş yerine tek bir çekirdek hâline geliyor. Çekirdek gerçeklemelerini senin gerçek cihazında kıyaslayıp her katman için en hızlısını tutuyor. Ve belleği anlık ayırmak yerine baştan planlıyor.
Çıktı bir engine dosyası ve o engine, üzerinde derlendiği GPU’ya ve TensorRT sürümüne özgü. Onu masaüstünde değil, Jetson’ın kendisinde derle. JetPack yükselttiğinde de yeniden derlemeyi plana koy: bir TensorRT sürümüyle derlenen engine başka sürümde yüklenmez. Bunun JetPack tarafını Jetson kurulumu yazısında anlatmıştım.
FP16: bitlerin yarısı, kaybın çoğu zaman sıfırı
FP16, ağırlıkları ve aktivasyonları 32 yerine 16 bitte tutuyor. Bellek trafiği yarıya iniyor ve Jetson sınıfı donanımda hızlı tensor core yolları açılıyor. Herkesin sorduğu soru, bunun doğruluğa maliyeti.
Dürüst cevap: ölç, çünkü cevap deneysel. Bizim dedektörde FP16 engine’in doğrulama sonuçları FP32 checkpoint ile gürültü sınırları içinde aynıydı. Tespit modellerinde yaygın durum bu, ama doğa kanunu değil. Bütün doğrulama setini checkpoint’ten değil, gerçek engine’den geçir ve karşılaştır. Sayılar tutuyorsa FP16 bedava performanstır.
Neden ölçmeden güvenmiyorum? Çünkü FP16’nın temsil aralığı FP32’den dar ve bazı ağlarda ara aktivasyonlar o aralığın kenarına yaslanıyor. Tespit modellerinde bu nadiren görünür bir soruna dönüşüyor, ama dönüştüğünde kendini metrik tablosunda değil, sahada tek tük kaçan hedeflerde gösteriyor. Birkaç dakikalık bir doğrulama koşusu bu belirsizliği tartışma konusu olmaktan çıkarıyor.
Bir alt basamak INT8 ve o başka bir hayvan: kalibrasyon verisi istiyor ve doğruluk gerçek ilgi istemeye başlıyor. Kuralım basit. FP16’yı varsayılan olarak al, INT8’i ancak hâlâ pay gerekiyorsa hak et.
Checkpoint’ten engine’e: gerçekte koştuğum zincir
Zincirim bilerek sıkıcı: PyTorch checkpoint’ten ONNX’e, ONNX’ten TensorRT engine’e, engine’den Jetson’a. ONNX teslim noktası. Export, dinamik PyTorch grafını statik bir grafa donduruyor ve problemi temiz ikiye bölüyor: ONNX dosyasından önce yanlış olan her şey eğitim tarafının hatası, sonrasındaki her şey sahaya alma tarafının. Bir şey kırıldığında bu bölünme, sistemin hangi yarısını açacağını sana söylüyor.
Bu zinciri sayamayacağım kadar çok koşturmaktan iki pratik not. Birincisi, giriş çözünürlüğünü export anında sabitle ve eğitim ile doğrulamada kullandığınla aynı olsun. Bir boyutta export edilip başka boyutta beslenen dedektör tek bir hata mesajı vermeden çalışır ve çöp skorlar. İkincisi, ONNX dosyasına geçici dosya değil gerçek bir artefakt muamelesi yap. Onu geldiği checkpoint’in yanında versiyonla, çünkü iki hafta sonra bir saha sonucu tuhaf göründüğünde soracağın ilk soru “bu engine hangi export’tan derlendi” olacak.
Bir de sürüm meselesi var. Zincirin üç halkası da, PyTorch, ONNX export’u ve TensorRT, kendi sürüm uyumluluğunu taşıyor. Çalışan bir kombinasyon bulduğunda onu bir kenara yaz. “En son sürüm” gömülü tarafta bir erdem değil, bir risk.
Ultralytics bu zinciri tek komuta indirip checkpoint’ten doğrudan engine’e gidebiliyor. Ben yine de açık ONNX adımını tek bir sebepten seviyorum: engine her şeyi içine gömmeden önce durup bakabileceğin bir yer bırakıyor.
Cihazda doğrula, kafanda değil
Export’un kendisi kısa: Ultralytics doğrudan TensorRT engine üretebiliyor ya da
ONNX çıkarıp trtexec ile derliyorsun. İnsanların atladığı kısım doğrulama, o
yüzden listem şu.
Doğrulama setini sahaya alınmış engine’den geçir ve metrikleri checkpoint ile
karşılaştır. Ön işlemenin eşleştiğini teyit et: letterbox, normalizasyon, kanal
sırası. Buradaki sessiz bir uyumsuzluk sana hiçbir profiler’ın göstermeyeceği bir
doğruluk kaybettirir. Son işlemenin de eşleştiğini teyit et, çünkü
NMS ve güven eşiği istesen de istemesen de modelin
parçası. Ve çalışırken tegrastats izle, çünkü termal kısılan bir Jetson,
optimizasyonun verdiği her şeyi sessizce geri alır.
Bu listeyi kafamda tutmuyorum, script olarak tutuyorum. Export bittiğinde tek komut: doğrulama seti engine’den geçiyor, metrikler checkpoint’inkilerle yan yana yazılıyor, ön işleme parametreleri de çıktının başına damgalanıyor. İnsan hafızasına bırakılan kontrol, teslim haftasında ilk atlanan kontroldür.
Savunma tarafında aynı disiplini görünür ve termal kanallarda C++ üzerinden yürütüyoruz ve listenin hiçbir maddesi değişmiyor. Engine, eğitim ile saha arasında bir sözleşme. Niyeti değil, sözleşmeyi test et.
Vaka: SUAS dedektörü, best.pt’den gövdeye
Yukarıdakilerin hepsi tek bir uçağa bağlanana kadar soyut kalıyor, o yüzden bizimkini anlatayım. SUAS dedektörü, yaklaşık 15.000 görüntüyle eğitilmiş bir YOLOv11m. Bulması gereken nesneler, yere serilmiş mankenler ve çadırlar, 20-40 m irtifada 4K karede 80-120 piksel genişliğinde. O kareyi normal bir dedektör girişine küçültürsen hedefler eriyip gidiyor; biz de her kareyi 1280x1280 parçalara bölüp tespiti parça başına koşuyoruz. Eğitim epoch 33 civarında yakınsadı, erken durdurma koşuyu epoch 48’de kapattı; doğrulama setinde mAP50 = 0,904 ve mAP50-95 = 0,691 ile bitti.
Sahaya alma zinciri tam olarak yukarıda anlattığım zincirdi: PyTorch checkpoint’ten ONNX’e, ONNX’ten TensorRT FP16 engine’e ve engine, gerçekten uçan Jetson’ın üzerinde derlendi. FP16 burada basit bir sebepten önemliydi: parçalama işi katlıyor. Tek bir 4K kare bir 1280x1280 parça yığınına dönüşüyor ve Jetson buna gövdenin güç ve termal bütçesi içinde yetişmek zorunda. Parçalama bütçesini kapatan şey FP16 engine oldu.
Sana satmak istediğim alışkanlık yeniden ölçme. Her export’tan sonra, sadece ilkinden değil, bütün doğrulama setini engine’in kendisinden geçirip sayıları checkpoint’inkilerin yanına koyduk. Aynı veri, aynı metrikler, farklı yürütücü. Çoğu gün bu karşılaştırma sıkıcı, mesele de bu: sıkıcı olmadığı tek günde, bir ön işleme uyumsuzluğunu ya da bozuk bir export’u uçtuktan sonra değil uçmadan önce yakalamışsın demektir. Kısa versiyonu şu: model sahaya giderken yürütücü değiştiriyor ve her değişim, doğruluğu sessizce kaybetmek için bir fırsat. Boru hattının bütününü UAS görü sistemi sayfasında anlattım.
Aynı temkin bir kat yukarıda da geçerliydi. Dedektör, parçaları tekrar bütün bir görünüme diken bir haritalama hattını besliyor ve o dikiş hattına gerçek bir arazinin üzerinde güvenmeden önce onu yerde bir maket şehir üzerinde doğruladık. Ucuz prova, pahalı ders önlendi.

Kare: projenin gerçek çıktısı.