Kimlik-Farkında Negatif Örnekleme Neden Önemli
20 Haz 2026 · 3 dk okuma
Contrastive öğrenmede modelin ne kadar iyi temsil çıkardığı, büyük ölçüde ona "neyi neyden ayırması gerektiğini" gösteren negatif örneklerin niteliğine bağlıdır. Multimodal deepfake (sahtelik) tespitinde bu durum daha da kritik bir hâl alır: bir kişinin gerçek videosunu, aynı kişinin manipüle edilmiş videosundan ayırmak, rastgele iki kişiyi ayırmaktan çok daha zordur ve öğretici değeri de çok daha yüksektir. Bu yazıda, görünüşte masum bir tasarım tercihinin — batch'lerin nasıl oluşturulduğunun — modelin gördüğü negatiflerin kalitesini nasıl sessizce belirlediğini ve bunu fark edip düzelttiğimizde ne kazandığımızı anlatıyorum.
Sorunu kuran denklem
Kullandığımız contrastive loss'un (Denklem 5) kimlik-farkında negatif terimi, anlamlı olabilmek için belirli bir koşula ihtiyaç duyar: aynı kimliğe ait gerçek ve sahte örneklerin aynı batch içinde bir arada bulunması gerekir. Ancak bir batch'i tamamen rastgele doldurduğunuzda, bu eşleşmenin gerçekleşme olasılığı sandığınızdan çok daha düşüktür. Kimlik sayısı ve batch büyüklüğü olduğunda, belirli bir kimliğin karşıt örneğinin batch'e en az bir kez girme olasılığı kabaca şöyledir:
Tipik bir kurulumda ( yüzlerce, ) bu olasılık şaşırtıcı biçimde küçük çıkar. Pratikteki karşılığı şuydu: ilgili negatif, örneklerin yaklaşık %73'ünde batch içinde hiç bulunmuyordu. Yani loss'un en öğretici terimi, vakaların büyük çoğunluğunda devreye bile girmeden, hiçbir hata vermeden, sessizce atlanıyordu. Model "kimlik-farkında" bir kayıpla eğitildiğini sanıyordu; oysa o terim çoğu adımda boştaydı.
Çözüm: örnekleme katmanına müdahale
Sorunun kaynağı loss'un kendisinde değil, ona veri taşıyan örnekleme katmanında olduğu için, çözüm de oraya yapılmalıydı. Standart rastgele sampler yerine, batch'leri kimliklere göre gruplayan özel bir sampler tasarladık. Bu sampler her batch'i, seçtiği kimliklerin hem gerçek hem sahte örneklerini birlikte içerecek şekilde dolduruyor:
class IdentityGroupedBatchSampler(Sampler):
"""Aynı kimliğin gerçek + sahte örneklerini aynı batch'e koyar."""
def __init__(self, identities, batch_size, group_size=2):
self.groups = defaultdict(list)
for idx, ident in enumerate(identities):
self.groups[ident].append(idx)
self.batch_size = batch_size
self.group_size = group_size
def __iter__(self):
# her batch'i kimlik başına group_size örnek çekerek doldur
...Bu değişiklikle birlikte eşleşme oranı frac → 1.0'a yükseldi; yani kimlik-farkında
negatif terimi artık neredeyse her adımda gerçekten devreye giriyordu. Önemli olan
ayrıntı şu: modelin mimarisinde, loss fonksiyonunda ya da hiperparametrelerinde
hiçbir şey değiştirmedik. Tek dokunduğumuz yer, batch'lerin nasıl kurulduğuydu.
Sonuçların okunuşu
| Sampler | Eşleşme oranı | Δ Doğruluk |
|---|---|---|
| Rastgele (b=24) | ~0.27 | taban |
| Identity-grouped | ~1.00 | +X.XX |
Tablonun anlattığı asıl ders, tek bir doğruluk sayısının ötesinde. "Bir loss terimini eklemek" ile "o terimin gerçekten çalışması" arasında, çoğu zaman gözden kaçan bir uçurum vardır ve bu uçurum sıklıkla veri örnekleme katmanında saklanır. Bir kaybı koda eklemiş olmanız, onun her eğitim adımında etkili biçimde gradyana katkı verdiği anlamına gelmez; arada, batch kompozisyonu gibi sessiz ama belirleyici bir aracı durur. Bu nedenle bir bileşenin "açık" olduğunu varsaymadan önce, onun fiilen ne sıklıkla aktive olduğunu ölçmek, contrastive kurulumlarda neredeyse her zaman karşılığını veren bir alışkanlıktır.
Devamı
İzleyen bir yazıda, benzer biçimde gözden kaçan bir başka tutarsızlığa — eğitim ile değerlendirme aşamalarındaki referans dağılımı uyuşmazlığına — gireceğim; orada da kök neden, modelin kendisinde değil, onu besleyen veri akışında ortaya çıkıyor.