Ders 06 / 22
Tespit Mühendisliği
Sekiz taktik sütunu ve 26 teknik satırı olan kurgu bir sınıflandırma matrisinde iki kural sürümü karşılaştırılır: sürüm 1'in 6 kuralı 11 tekniği kapsıyor ama yalnız 8'i ateşlenebilir, 15 teknik hiç kapsanmıyor; sürüm 2'nin 11 kuralı 24 tekniği kapsıyor, 19'u ateşlenebilir, hiç kapsanmayan 2'ye iniyor. 51 kurgu örnek üzerinde sürüm 1 10 örnek yakalıyor, sürüm 2 30; kaçırmanın nedeni ayrıştırıldığında kural yokluğu 32'den 3'e inerken kaynak yokluğu 4'ten 11'e çıkıyor. Ek 220 dakikalık yazma işi örnek başına 11 dakikaya geliyor, günlük yanlış pozitif 30'dan 27'ye düşüyor ama inceleme yükü 360 dakikadan 513 dakikaya çıkıyor.
İçindekiler
Bir önceki derste bandı daraltan şey eşik ayarı değil, yeni bir öznitelikti — yani puanlamanın kendisinin değişmesi. Bu, bir kuralın ayarlanması değil yeniden yazılmasıdır ve düzenli yapılan bir iştir. Tespit mühendisliği o işin adıdır: kural yaz, koştur, kaçırdığını ölç, düzelt.
Döngünün ölçüsü kaç kural yazıldığı olamaz, çünkü kural sayısı ne kapsamayı ne de doğruluğu verir. Bu ders ölçüyü bir sınıflandırma matrisi üzerinden kurar. Matris yapısıyla ele alınır: sütunlar taktik, satırlar tekniktir; buradaki teknikler ve izleri kurgudur ve gerçek bir sınıflandırma çalışmasının içeriğine karşılık gelmez.
- TA28. Matriste 8 taktik sütunu ve 26 teknik satırı vardır. Her teknik satırı, izinin hangi kaynağa düştüğüyle etiketlidir.
- TA29. Bir teknik üç durumdan birindedir: izi toplanan bir kaynağa düşer, izi toplanmayan bir kaynağa düşer, ya da hiçbir kaynakta iz bırakmaz. Son iki durumda kural yazılabilir ama ateşlenemez.
- TA30. Kural bir veya birkaç tekniği kapsar. Her kuralın üç sayısı vardır: yazma ve ayarlama dakikası, duyarlılık, günlük yanlış pozitif. Üçü de model verisidir.
- TA31. Kapsanan teknik, en az bir kuralın hedeflediği tekniktir. Ateşlenebilir kapsama, bunun kaynağı toplanan alt kümesidir. İkisi arasındaki fark kağıt üstünde kalan kapsamadır.
- TA32. Örnek kümesi tekniklerin kurgu örneklerinden oluşur ve iki sürüm için aynıdır; karşılaştırmanın anlamı buna bağlıdır.
Matriste Kapsama ve İki Sürüm
// kapsam.mjs — taktik ve teknik matrisinde iki kural surumunun kapsamasi. MODELDIR. // Matris yapisiyla ele alinir: sutunlar taktik, satirlar teknik. Teknikler kurgudur. export const TAKTIK = [["ilk erisim", 3], ["calistirma", 4], ["kalicilik", 4], ["yetki yukseltme", 3], ["kimlik bilgisi elde etme", 4], ["kesif", 3], ["yanal hareket", 3], ["sizdirma", 2]]; // Her teknigin izi hangi kaynakta duser: K kimlik, U uc nokta, A ag akisi, // Y yonetim duzlemi, S toplanMAYAN sunucu uygulama gunlugu, - hicbir kaynakta iz yok. const IZ = "KUS UAUY U-UA KYS K-UY AAU S-K AA".replace(/ /g, "").split(""); export const TEKNIK = []; for (const [taktik, n] of TAKTIK) for (let k = 0; k < n; k++) { const i = TEKNIK.length; TEKNIK.push({ id: `t${String(i + 1).padStart(2, "0")}`, taktik, iz: IZ[i] }); } // Hatta toplanan kaynaklar (model verisi). S kaynagi vardir ama toplanmamaktadir. export const TOPLANAN = new Set(["K", "U", "Y", "A"]); // Kural: [ad, kapsadigi teknik indeksleri, yazma+ayarlama dakikasi, duyarlilik, gunluk yanlis poz.] export const SURUM1 = [["s1", [0, 2], 90, 0.8, 3], ["s2", [6, 8], 120, 0.7, 5], ["s3", [12, 16], 150, 0.6, 4], ["s4", [20, 23], 90, 0.75, 2], ["s5", [1, 13], 180, 0.5, 9], ["s6", [4], 240, 0.4, 7]]; export const SURUM2 = [["s1", [0, 2], 30, 0.85, 2], ["s2", [6, 8], 40, 0.8, 2], ["s3", [12, 16], 40, 0.7, 2], ["s4", [20, 23], 20, 0.8, 1], ["s5", [1, 13, 17], 60, 0.6, 3], ["s7", [3, 9], 150, 0.7, 3], ["s8", [5, 10, 14], 210, 0.65, 4], ["s9", [18, 21], 180, 0.55, 3], ["s10", [7, 11], 120, 0.5, 2], ["s11", [24, 25], 90, 0.6, 2], ["s12", [15, 19], 150, 0.45, 3]]; export function kapsama(kurallar) { const kapsanan = new Set(kurallar.flatMap(([, l]) => l)); const say = (f) => [...kapsanan].filter((i) => f(TEKNIK[i].iz)).length; return { kapsanan, atesle: new Set([...kapsanan].filter((i) => TOPLANAN.has(TEKNIK[i].iz))), toplanmayan: say((z) => z === "S"), izsiz: say((z) => z === "-"), hic: TEKNIK.length - kapsanan.size, dakika: kurallar.reduce((a, k) => a + k[2], 0), yp: kurallar.reduce((a, k) => a + k[4], 0) }; } if (import.meta.url === `file://${process.argv[1]}`) { const gen = (B) => (h) => h.map((v, j) => (j ? String(v).padStart(B[j]) : String(v).padEnd(B[0]))).join(""); const yt = gen([26, 8, 10, 12, 12]); const k1 = kapsama(SURUM1), k2 = kapsama(SURUM2); console.log(`matris: ${TAKTIK.length} taktik sutunu, ${TEKNIK.length} teknik satiri; ` + `${TEKNIK.filter((t) => t.iz === "S").length} teknigin kaynagi toplanmiyor, ` + `${TEKNIK.filter((t) => t.iz === "-").length} teknigin hicbir kaynakta izi yok`); console.log(); console.log(yt(["taktik", "teknik", "surum 1", "surum 2", "izi olmayan"])); for (const [taktik] of TAKTIK) { const l = TEKNIK.filter((t) => t.taktik === taktik); const say = (s) => l.filter((t) => s.has(TEKNIK.indexOf(t))).length; console.log(yt([taktik, l.length, say(k1.kapsanan), say(k2.kapsanan), l.filter((t) => !TOPLANAN.has(t.iz)).length])); } const yk = gen([10, 8, 12, 15, 14, 10, 16, 11]); console.log(); console.log(yk(["surum", "kural", "kapsanan", "ateslenebilir", "kaynagi yok", "izi yok", "hic kapsanmaz", "yazma dk"])); for (const [ad, k, l] of [["surum 1", k1, SURUM1], ["surum 2", k2, SURUM2]]) console.log(yk([ad, l.length, `${k.kapsanan.size}/${TEKNIK.length}`, `${k.atesle.size}/${TEKNIK.length}`, k.toplanmayan, k.izsiz, k.hic, k.dakika])); }
matris: 8 taktik sutunu, 26 teknik satiri; 3 teknigin kaynagi toplanmiyor, 3 teknigin hicbir kaynakta izi yok taktik teknik surum 1 surum 2 izi olmayan ilk erisim 3 3 3 1 calistirma 4 2 3 0 kalicilik 4 1 4 1 yetki yukseltme 3 2 3 1 kimlik bilgisi elde etme 4 1 4 1 kesif 3 1 3 0 yanal hareket 3 1 2 2 sizdirma 2 0 2 0 surum kural kapsanan ateslenebilir kaynagi yok izi yok hic kapsanmaz yazma dk surum 1 6 11/26 8/26 2 1 15 870 surum 2 11 24/26 19/26 3 2 2 1090
Taktik tablosu ilk bulguyu veriyor: sürüm 1’in kapsaması eşit dağılmamıştır. İlk erişim satırının üçü de kapsanıyor, sızdırma satırının hiçbiri kapsanmıyor. Bu, tespit yazımının doğal eğilimidir — kolay kural, alanları ayırt edici olan kaynakta yazılır ve o kaynak genellikle zincirin başındadır. Sonuç bir kapsama haritasında değil, kaçırılan kalemlerde görünür. Sızdırma satırının boş kalması, o taktiğin önemsiz görülmesinden değil, izinin ağ akış verisinde bulunmasından ve o kaynakta ayırt edici bir kural yazmanın dördüncü derste ölçülmüş güçlüğünden gelir.
Alt tablodaki iki sütun arasındaki fark dersin ana kavramıdır. Sürüm 1 on bir tekniği kapsıyor ama yalnız sekizi ateşlenebilir: üç teknikte kural vardır ve hiçbir zaman tetiklenmez. Bunların ikisinde kaynak vardır ama hatta toplanmıyor, birinde teknik hiçbir kaynakta iz bırakmıyor. “Yirmi altı tekniğin on birini kapsıyoruz” cümlesi bu ayrım yazılmadığında yanlış bir cümledir.
Sürüm 2 kapsamayı 24’e, ateşlenebilir kapsamayı 19’a çıkarıyor ve hiç kapsanmayanı 15’ten 2’ye indiriyor. Kalan iki tekniğin biri hiçbir kaynakta iz bırakmadığı için kapsanamaz; öteki kapsanabilirdi ama sürüm 1’deki bir kural döngüde kaldırıldı. Yazma işi 870 dakikadan 1.090 dakikaya çıktı; bu sayı yeni kuralların yanı sıra eski kuralların ayarlanmasını da içerir ve ilk dört kuralın ikinci sürümdeki dakikaları belirgin biçimde düşüktür, çünkü ayarlamak yazmaktan ucuzdur.
Sürümleri Aynı Örnek Kümesinde Koşturmak
// dongu.mjs — iki kural surumu kurgu ornek kumesinde kosturulur; kacirmanin nedeni ayrilir. import { TEKNIK, TOPLANAN, SURUM1, SURUM2, kapsama } from "./kapsam.mjs"; const uretec = (t) => { let s = t >>> 0; return () => (s = (s * 1664525 + 1013904223) >>> 0) / 4294967296; }; const INCELEME = 9; // Kurgu ornek kumesi: her teknikten 0-4 ornek. Ornek sayisi VERIDIR. const ORNEK = []; { const r = uretec(20260406); for (const [i] of TEKNIK.entries()) for (let k = 0, n = Math.floor(r() * 5); k < n; k++) ORNEK.push({ teknik: i, z: r() }); } function kostur(kurallar) { const k = kapsama(kurallar); const sonuc = { yakalanan: 0, kuralYok: 0, kaynakYok: 0, duyarlilik: 0 }; const atesleyen = new Set(), pay = new Map(kurallar.map(([ad]) => [ad, 0])); for (const o of ORNEK) { const kapsayan = kurallar.filter(([, l]) => l.includes(o.teknik)); if (kapsayan.length === 0) { sonuc.kuralYok++; continue; } if (!TOPLANAN.has(TEKNIK[o.teknik].iz)) { sonuc.kaynakYok++; continue; } const en = Math.max(...kapsayan.map(([, , , d]) => d)); if (o.z < en) { sonuc.yakalanan++; kapsayan.forEach(([ad]) => { atesleyen.add(ad); pay.set(ad, pay.get(ad) + 1); }); } else sonuc.duyarlilik++; } const olu = kurallar.filter(([ad]) => !atesleyen.has(ad)).map(([ad, l]) => { const tk = l.filter((i) => !TOPLANAN.has(TEKNIK[i].iz)).length; const orn = ORNEK.filter((o) => l.includes(o.teknik)).length; return `${ad} (${l.length} teknik, ${tk} tanesinin kaynagi yok, ${orn} ornek)`; }); return { ...sonuc, yp: k.yp, dakika: k.dakika, olu, pay, inceleme: (sonuc.yakalanan + k.yp) * INCELEME }; } const gen = (B) => (h) => h.map((v, j) => (j ? String(v).padStart(B[j]) : String(v).padEnd(B[0]))).join(""); const yz = gen([10, 8, 11, 11, 12, 13, 13, 13]); console.log(`kurgu ornek kumesi: ${ORNEK.length} ornek, ${TEKNIK.length} teknige dagilmis`); console.log(); console.log(yz(["surum", "ornek", "yakalanan", "kural yok", "kaynak yok", "duyarlilik", "yanlis poz.", "inceleme dk"])); const [a, b] = [SURUM1, SURUM2].map(kostur); for (const [ad, s] of [["surum 1", a], ["surum 2", b]]) console.log(yz([ad, ORNEK.length, s.yakalanan, s.kuralYok, s.kaynakYok, s.duyarlilik, s.yp, s.inceleme])); console.log(`\nhic ateslenmeyen kural — surum 1: ${a.olu.join(", ") || "yok"}; ` + `surum 2: ${b.olu.join(", ") || "yok"}`); console.log(`surum 2 ek ${b.dakika - a.dakika} dakika yazma isiyle ` + `${b.yakalanan - a.yakalanan} ek ornek yakaliyor: ornek basina ` + `${Math.round((b.dakika - a.dakika) / (b.yakalanan - a.yakalanan))} dakika`); console.log(`gunluk yanlis pozitif ${a.yp} -> ${b.yp}, gunluk inceleme ` + `${a.inceleme} -> ${b.inceleme} dakika`); const yp = gen([8, 9, 13, 12, 12, 11, 17]); console.log("\nsurum 2 kural bazinda:"); console.log(yp(["kural", "teknik", "kaynagi yok", "yakaladigi", "gunluk yp", "yazma dk", "ornek basina dk"])); for (const [ad, l, dk, , fp] of SURUM2) { const n = b.pay.get(ad); console.log(yp([ad, l.length, l.filter((i) => !TOPLANAN.has(TEKNIK[i].iz)).length, n, fp, dk, n ? Math.round(dk / n) : "-"])); }
kurgu ornek kumesi: 51 ornek, 26 teknige dagilmis surum ornek yakalanan kural yok kaynak yok duyarlilik yanlis poz. inceleme dk surum 1 51 10 32 4 5 30 360 surum 2 51 30 3 11 7 27 513 hic ateslenmeyen kural — surum 1: s6 (1 teknik, 0 tanesinin kaynagi yok, 1 ornek); surum 2: s9 (2 teknik, 1 tanesinin kaynagi yok, 3 ornek) surum 2 ek 220 dakika yazma isiyle 20 ek ornek yakaliyor: ornek basina 11 dakika gunluk yanlis pozitif 30 -> 27, gunluk inceleme 360 -> 513 dakika surum 2 kural bazinda: kural teknik kaynagi yok yakaladigi gunluk yp yazma dk ornek basina dk s1 2 1 1 2 30 30 s2 2 1 4 2 40 10 s3 2 0 3 2 40 13 s4 2 0 3 1 20 7 s5 3 1 4 3 60 15 s7 2 0 5 3 150 30 s8 3 0 1 4 210 210 s9 2 1 0 3 180 - s10 2 0 3 2 120 40 s11 2 0 5 2 90 18 s12 2 1 1 3 150 150
Kaçırmanın üç nedeni ayrı sütunlarda duruyor ve döngünün ne yaptığını tam olarak bu ayrım gösteriyor. Sürüm 1’de 41 kaçırmanın 32’si kural yokluğundandır; sürüm 2’de bu sayı 3’e iner. Buna karşılık kaynak yokluğu 4’ten 11’e çıkar. Bu artış bir gerileme değildir: kural yazıldıkça, kaçırmanın nedeni kural eksikliğinden kaynak eksikliğine kayar. İkinci sütun tükendiğinde geriye kalan sayı kural yazarak azaltılamaz; toplama kararı gerektirir.
Duyarlılık sütunu üçüncü nedeni tutuyor: kural var, kaynak var, ama örnek kuralın eşiğini geçmedi. Bu sayı 5’ten 7’ye çıkıyor, çünkü sürüm 2 daha çok tekniği kapsıyor ve yeni kuralların duyarlılığı düşüktür. Bir kural kümesini büyütmek, kaçırmanın dağılımını değiştirir; her nedeni birden küçültmez. Üç sütunun üçü de ayrı bir işe karşılık gelir: birincisi kural yazmayı, ikincisi toplama kararını, üçüncüsü bir önceki dersteki eşik ve öznitelik çalışmasını gerektirir. Aynı sayıyı “kaçırılan” diye tek sütunda toplamak, hangi işin yapılacağını belirsiz bırakır.
Ölü kural satırı bakımın gizli kalemidir. Sürüm 1’de s6 hiç ateşlenmedi ve o kural 240 dakika yazma işi tüketmişti; sürüm 2’de s9 hiç ateşlenmedi ve kapsadığı iki teknikten birinin kaynağı zaten toplanmıyor. Ölü kural bir kapsama tablosunda kapsanan olarak görünür, bir uyarı listesinde hiç görünmez ve her sürüm yükseltmesinde yeniden gözden geçirilir.
Döngünün faturası şudur: ek 220 dakikalık yazma işi 20 ek örnek yakalıyor, örnek başına 11 dakika. Günlük yanlış pozitif 30’dan 27’ye iniyor — kural sayısı neredeyse ikiye katlandığı hâlde düşüyor, çünkü sürüm 1’in en gürültülü kuralı kaldırıldı. Ama günlük inceleme yükü 360 dakikadan 513 dakikaya çıkıyor: doğru tespitin de bir inceleme maliyeti vardır ve iyi bir kural kümesi vardiyayı rahatlatmaz, doldurur.
Kural bazındaki son tablo ortalamanın gizlediğini açıyor. Örnek başına dakika sütunu 7 ile 210 arasında değişiyor: s4 yirmi dakikalık ayarlamayla üç örnek yakalıyor, s8 iki yüz on dakikalık yazma işiyle bir örnek. İkisi de kapsama tablosunda birer satırdır ve orada aynı görünürler. Kapsamayı ölçü almak bu yüzden yetmez; kapsanan gözün kaç örnek getirdiği ayrı bir sayıdır.
Aynı tabloda kaynagi yok sütunu beş kuralda sıfırdan büyüktür. Bu kurallar iki teknik kapsadıkları
hâlde yalnız birinde ateşlenebilir; kapsama sayımına iki, ateşlenebilir sayıma bir katkı verirler.
En uç örnek s9’dur: iki teknik, biri toplanmayan kaynakta, gün boyu sıfır yakalama, 180 dakika
yazma işi. Bir kuralın iyi ya da kötü olduğu ancak koşturulduktan sonra söylenebilir ve koşturmanın
kendisi bu döngünün asıl adımıdır.
Özet
- Kapsanan teknik ile ateşlenebilir kapsama ayrı sayılır: sürüm 1 on bir tekniği kapsıyor ama yalnız sekizi ateşlenebilir, üçünde kural vardır ve hiçbir zaman tetiklenmez.
- Kapsama taktikler arasında eşit dağılmıyor; sürüm 1 ilk erişim satırının üçünü de kapsarken sızdırma satırının hiçbirini kapsamıyor.
- Sürüm 2 kapsamayı 24’e, ateşlenebilir kapsamayı 19’a çıkarıyor ve hiç kapsanmayanı 15’ten 2’ye indiriyor; kalan ikiden biri hiçbir kaynakta iz bırakmadığı için kapsanamaz.
- Kural yazıldıkça kaçırmanın nedeni kayıyor: kural yokluğu 32’den 3’e inerken kaynak yokluğu 4’ten 11’e çıkıyor ve o sayı kural yazarak azaltılamaz.
- Ek 220 dakikalık yazma işi örnek başına 11 dakikaya geliyor; günlük yanlış pozitif 30’dan 27’ye düşerken inceleme yükü 360 dakikadan 513 dakikaya çıkıyor.
- Kural bazında verim 7 ile 210 dakika arasında değişiyor ve kapsama tablosunda bu fark görünmez; s9 iki tekniği kapsadığı hâlde hiç ateşlenmiyor ve 180 dakikalık yazma işi karşılıksız kalıyor.
Sonraki Adım
Sürüm 2’den sonra 51 örneğin 21’i hâlâ kaçıyor ve bunların 11’i hiçbir kuralın ulaşamayacağı yerde: kaynağı toplanmayan ya da hiç iz bırakmayan tekniklerde. Kural yazmak bu sayıyı azaltmaz, çünkü kural ancak sorabildiği alanı sorar. Sonraki ders başka bir yoldan gider: kuraldan değil, hipotezden başlar. Bir hipotez veri kümesine bir soru sorar ve yanıtı bir uyarı değil, elenen kalem sayısıdır. Ölçü orada hipotez başına kaç kalemin elendiği, kaç hipotezin sıfır sonuç verdiği ve elenen kalemlerin kaçının yeni bir kurala dönüştüğüdür.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.