İçeriğe geç
academia.sh

Ders 04 / 11

Risk Kaydı

Belirsizliğin bir kayıt üzerinden izlenmesi: riskler olasılık ve etkiyle modellenir, bir dönem tohumu görünür bir üreteçle koşturulur, kayıttaki olasılık tahmini ile ölçülen gerçekleşme oranı bantlar halinde karşılaştırılır, hiç kaydedilmediği halde gerçekleşen riskler sayılır ve gözden geçirme sıklığının gerçekleşmeden önce yakalanan risk sayısına etkisi kişi-dakika karşılığıyla birlikte ölçülür.

İçindekiler

Önceki üç ders verilmiş bir kararın kaydını, verilme sürecini ve dayandığı tabloyu ölçtü. Üçünde de karar bir noktada kesinleşir ve kayıt kapanır. Kapanmayan bir şey kalır: kararın dayandığı varsayımın tutmama ihtimali. Ödünleşim çözümlemesinde bir ölçüte 0,50 ağırlık verilmesi, o niteliğin kritik olduğu varsayımına dayanır; varsayım yanlışsa karar da yanlıştır ve bunu ancak zaman gösterir.

Bu, kayda geçirilecek bir karar değil, izlenecek bir belirsizliktir ve kendi kaydını gerektirir. Riskin test bütçesini nasıl böldüğü test planlama konusunda ölçüldü; burada tekrarlanmaz. Buradaki soru kaydın kendisiyle ilgilidir: kayıt tutulduğunda ne yakalanıyor, ne kaçıyor ve kaydın ne sıklıkta gözden geçirildiği bunu nasıl değiştiriyor.

Risk Kaydı ve Bir Dönem

Risk kaydı iki alanla modellenir: olasılık ve etki. Olasılık kayda yazılan bir tahmindir; etki gerçekleştiğinde ne kadar iş çıkaracağının ölçeğidir. Modeldeki on dört riskin sekizi kayıtta, altısı kayıt dışıdır — kayıt dışı olanlar sistemde vardır, kimse yazmamıştır.

Her riskin iki olasılığı ayrılır: kayda yazılan tahmin ve dönem boyunca gözlenen davranışı belirleyen gerçek olasılık. İkincisi modelin girdisidir (KK12); kayıt tutan kişi onu görmez, yalnızca dönemler geçtikçe ölçer. Beş yüz dönem koşturulur ve üreteç kendi yazılır, tohum görünürdür.

// risk/kayit.mjs — risk kaydi olasilik ve etkiyle modellenir, bir donem kosturulur
// [ad, kayittaki tahmin (null ise kayitta yok), gercek olasilik, etki]; hepsi modelin girdisi (KK12)
export const RISK = [
  ["katalog-surum-kirilmasi", 0.60, 0.55, 4],
  ["sube-agi-kopmasi", 0.70, 0.75, 3],
  ["onbellek-tazelik-asimi", 0.50, 0.15, 3],
  ["kimlik-servisi-kesintisi", 0.40, 0.35, 5],
  ["yedekleme-penceresi-tasmasi", 0.30, 0.45, 2],
  ["uye-verisi-uyumsuzlugu", 0.20, 0.20, 5],
  ["kart-basim-gecikmesi", 0.15, 0.10, 2],
  ["kural-motoru-buyumesi", 0.10, 0.50, 3],
  ["arama-dizini-tutarsizligi", null, 0.40, 3],
  ["rapor-sunucusu-yetersizligi", null, 0.35, 4],
  ["bildirim-kuyrugu-birikmesi", null, 0.30, 2],
  ["lisans-yenileme-gecikmesi", null, 0.25, 4],
  ["sube-personeli-egitim-eksigi", null, 0.20, 2],
  ["odunc-limiti-istisnasi", null, 0.15, 1],
].map(([ad, tahmin, gercek, etki]) => ({ ad, tahmin, gercek, etki, kayitli: tahmin !== null }));

export const AY = 12;                    // bir donem
export const rastgele = (tohum) => () => {   // uretec burada yazilir, tohum gorunurdur
  tohum = (tohum + 0x6d2b79f5) | 0;
  let t = Math.imul(tohum ^ (tohum >>> 15), 1 | tohum);
  t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t;
  return ((t ^ (t >>> 14)) >>> 0) / 4294967296;
};

// Bir donem: her risk gercek olasiligiyla gerceklesir, gerceklesirse ayi duzgun dagilir.
export function donem(rnd) {
  return RISK.map((r) => {
    const oldu = rnd() < r.gercek;
    return { risk: r, oldu, ay: oldu ? 1 + Math.floor(rnd() * AY) : null };
  });
}

export const BANT = (p) => (p >= 0.5 ? "yuksek" : p >= 0.2 ? "orta" : "dusuk");

if (import.meta.url.endsWith(process.argv[1].split("/").pop())) {
  const TEKRAR = 500, TOHUM = 20240517, rnd = rastgele(TOHUM);
  const kez = RISK.map(() => 0);
  for (let i = 0; i < TEKRAR; i++)
    donem(rnd).forEach((s, j) => { if (s.oldu) kez[j] += 1; });
  const olculen = kez.map((k) => k / TEKRAR);
  const kayitli = RISK.filter((r) => r.kayitli);
  const toplam = kez.reduce((t, k) => t + k, 0);
  const disi = RISK.reduce((t, r, j) => t + (r.kayitli ? 0 : kez[j]), 0);
  console.log(`${RISK.length} risk: ${kayitli.length} kayitli, ${RISK.length - kayitli.length} ` +
    `kayit disi; ${TEKRAR} donem, tohum ${TOHUM}`);
  console.log(`gerceklesen risk ${toplam}, bunlarin ${disi} tanesi kayit disi ` +
    `(%${(100 * disi / toplam).toFixed(1)})\n`);

  console.log("kayittaki tahmin bandi ile olculen gerceklesme orani:");
  for (const bant of ["yuksek", "orta", "dusuk"]) {
    const g = RISK.map((r, j) => ({ r, o: olculen[j] })).filter((x) => x.r.kayitli && BANT(x.r.tahmin) === bant);
    console.log(`  ${bant.padEnd(7)} ${g.length} risk, ortalama tahmin ` +
      `${(g.reduce((t, x) => t + x.r.tahmin, 0) / g.length).toFixed(2)}, olculen oran ` +
      `${(g.reduce((t, x) => t + x.o, 0) / g.length).toFixed(2)}`);
  }
  console.log("\ntahmini olculen orandan en cok sapan kayitli riskler:");
  for (const x of RISK.map((r, j) => ({ r, o: olculen[j] })).filter((x) => x.r.kayitli)
    .sort((a, b) => Math.abs(b.o - b.r.tahmin) - Math.abs(a.o - a.r.tahmin)).slice(0, 3))
    console.log(`  ${x.r.ad.padEnd(28)} tahmin ${x.r.tahmin.toFixed(2)} olculen ${x.o.toFixed(2)} ` +
      `sapma ${(x.o - x.r.tahmin > 0 ? "+" : "") + (x.o - x.r.tahmin).toFixed(2)} etki ${x.r.etki}`);
  console.log("\nkayit disi kalip gerceklesen riskler (olculen oran x etki):");
  for (const x of RISK.map((r, j) => ({ r, o: olculen[j] })).filter((x) => !x.r.kayitli)
    .sort((a, b) => b.o * b.r.etki - a.o * a.r.etki))
    console.log(`  ${x.r.ad.padEnd(28)} olculen ${x.o.toFixed(2)} etki ${x.r.etki} ` +
      `carpim ${(x.o * x.r.etki).toFixed(2)}`);
}
14 risk: 8 kayitli, 6 kayit disi; 500 donem, tohum 20240517
gerceklesen risk 2348, bunlarin 808 tanesi kayit disi (%34.4)

kayittaki tahmin bandi ile olculen gerceklesme orani:
  yuksek  3 risk, ortalama tahmin 0.60, olculen oran 0.49
  orta    3 risk, ortalama tahmin 0.30, olculen oran 0.34
  dusuk   2 risk, ortalama tahmin 0.13, olculen oran 0.30

tahmini olculen orandan en cok sapan kayitli riskler:
  kural-motoru-buyumesi        tahmin 0.10 olculen 0.50 sapma +0.40 etki 3
  onbellek-tazelik-asimi       tahmin 0.50 olculen 0.15 sapma -0.35 etki 3
  yedekleme-penceresi-tasmasi  tahmin 0.30 olculen 0.45 sapma +0.15 etki 2

kayit disi kalip gerceklesen riskler (olculen oran x etki):
  rapor-sunucusu-yetersizligi  olculen 0.35 etki 4 carpim 1.41
  arama-dizini-tutarsizligi    olculen 0.39 etki 3 carpim 1.18
  lisans-yenileme-gecikmesi    olculen 0.24 etki 4 carpim 0.98
  bildirim-kuyrugu-birikmesi   olculen 0.29 etki 2 carpim 0.59
  sube-personeli-egitim-eksigi olculen 0.18 etki 2 carpim 0.36
  odunc-limiti-istisnasi       olculen 0.15 etki 1 carpim 0.15

İlk sayı kaydın kapsama alanını veriyor: gerçekleşen 2348 riskin 808’i, yani yüzde 34,4’ü kayıtta hiç yoktu. Risk kaydının ölçülebilir ilk niteliği içindekilerin ne kadar doğru tahmin edildiği değil, dışında ne kaldığıdır. Sekiz maddelik bir kayda bakan biri, gerçekleşen olayların üçte birini hiç görmemiş olur.

Bant tablosu ikinci sayıyı veriyor ve kaydın kendi içindeki doğruluğunu gösteriyor. Yüksek bandın ortalama tahmini 0,60, ölçülen oranı 0,49; düşük bandın tahmini 0,13, ölçülen oranı 0,30. Bantlar sıralamayı bile korumuyor: düşük diye işaretlenmiş riskler orta banda yakın bir sıklıkla gerçekleşiyor. Bir risk kaydının olasılık sütunu, ölçülen oranla karşılaştırılmadığı sürece bir sıralama değil, bir izlenim listesidir.

Sapma tablosu bu bozulmanın nereden geldiğini gösteriyor. kural-motoru-buyumesi 0,10 tahmin edilmişti, 0,50 ölçüldü; onbellek-tazelik-asimi 0,50 tahmin edilmişti, 0,15 ölçüldü. İki sapma zıt yönde ve ikisi de büyük. Kayda bakan biri ikinci riske hazırlanır, birinciyle karşılaşır. Bu, kaydın gözden geçirilmesinin neden bir formalite olmadığını gösteren sayıdır: tahmin bir kez yazılıp bırakıldığında yanlışlığı kendini göstermez.

Son tablo kayıt dışı kalanları etkiyle birlikte sıralıyor. En üstteki iki madde, rapor-sunucusu-yetersizligi ve arama-dizini-tutarsizligi, çarpım olarak kayıttaki pek çok maddenin üzerinde. Kayıt dışı kalmalarının nedeni önemsiz olmaları değil, kimsenin akla getirmemesidir.

Gözden Geçirme Sıklığı

Kayıt dışı bir risk kendiliğinden kayda girmez; birinin onu fark etmesi gerekir. Fark etme, kaydın gözden geçirildiği anlarda olur. Aşağıdaki koşum dört sıklığı aynı dönemler üzerinde karşılaştırır: hiç gözden geçirmemek, yılda bir, üç ayda bir ve ayda bir. Bir gözden geçirmede kayıt dışı bir riskin fark edilme olasılığı ile gözden geçirmenin kişi-dakikası modelin girdisidir (KK13).

Ölçülen şey fark edilen risk sayısı değil, gerçekleşmeden önce fark edilen risk sayısıdır. Bir riski gerçekleştikten sonra kayda geçirmek kaydı düzeltir, olayı önlemez.

// risk/gozden.mjs — gozden gecirme sikligi kac riski gerceklesmeden once yakaliyor
import { RISK, AY, rastgele, donem } from "./kayit.mjs";

const FARK = 0.20;        // bir gozden gecirmede kayit disi bir riskin fark edilme olasiligi (KK13)
const KISI_DK = 45;       // bir gozden gecirmenin kisi-dakikasi (KK13)
const SIKLIK = {
  hic: [], yillik: [12], "uc-aylik": [3, 6, 9, 12], aylik: [...Array(AY)].map((_, i) => i + 1),
};

const TEKRAR = 500, TOHUM = 20240518;
console.log(`${TEKRAR} donem, tohum ${TOHUM}; fark etme olasiligi ${FARK}, ` +
  `gozden gecirme basina ${KISI_DK} kisi-dk`);
console.log("siklik      gecirme  fark edilen  onceden yakalanan  kayit disi gerceklesen  kisi-dk");

const sonuc = {};
for (const [ad, aylar] of Object.entries(SIKLIK)) {
  const rnd = rastgele(TOHUM);       // her siklik ayni tohumla, ayni donemler uzerinde kosar
  let farkEdilen = 0, once = 0, kacan = 0;
  for (let i = 0; i < TEKRAR; i++)
    for (const s of donem(rnd)) {
      if (s.risk.kayitli) continue;
      let bulunduAy = null;
      for (const m of aylar) if (rnd() < FARK) { bulunduAy = m; break; }
      if (bulunduAy !== null) farkEdilen += 1;
      if (s.oldu && (bulunduAy === null || bulunduAy >= s.ay)) kacan += 1;
      else if (s.oldu) once += 1;
    }
  const kisiDk = aylar.length * KISI_DK;
  sonuc[ad] = { once: once / TEKRAR, kacan: kacan / TEKRAR, kisiDk, fark: farkEdilen / TEKRAR };
  console.log(`  ${ad.padEnd(10)} ${String(aylar.length).padStart(4)} ` +
    `${(farkEdilen / TEKRAR).toFixed(2).padStart(11)} ${(once / TEKRAR).toFixed(2).padStart(17)} ` +
    `${(kacan / TEKRAR).toFixed(2).padStart(22)} ${String(kisiDk).padStart(9)}`);
}

console.log("\nsikligi artirmanin karsiligi (donem basina):");
const ad = Object.keys(SIKLIK);
for (let i = 1; i < ad.length; i++) {
  const a = sonuc[ad[i - 1]], b = sonuc[ad[i]];
  const ek = b.once - a.once;
  console.log(`  ${ad[i - 1]} -> ${ad[i]}: +${(b.kisiDk - a.kisiDk)} kisi-dk, ` +
    `+${ek.toFixed(2)} onceden yakalanan risk -> risk basina ` +
    `${ek > 0 ? `${((b.kisiDk - a.kisiDk) / ek).toFixed(0)} kisi-dk` : "karsiligi yok"}`);
}

// Soru kumesi: 14 risk x 3 soru; donem sonunda kayitta olan risk sayisina gore beklenen deger
const KAYITLI = RISK.filter((r) => r.kayitli).length, N = RISK.length;
console.log(`\nsoru kumesi (${N} risk x 3 soru = ${3 * N} yanit; R1 bu risk dusunuldu mu, ` +
  `R2 olasiligi ne kabul edilmisti, R3 tahmin tuttu mu):`);
for (const [ad, aylar] of Object.entries(SIKLIK)) {
  const kayitta = KAYITLI + sonuc[ad].fark, disi = N - kayitta;
  const dogru = kayitta * (aylar.length ? 3 : 2);
  const eksik = disi * 2 + (aylar.length ? 0 : kayitta);
  console.log(`  ${ad.padEnd(10)} kayitta ${kayitta.toFixed(2)}/${N} risk -> dogru ` +
    `${dogru.toFixed(1)}, eksik ${eksik.toFixed(1)}, yanlis ${disi.toFixed(1)}`);
}
500 donem, tohum 20240518; fark etme olasiligi 0.2, gozden gecirme basina 45 kisi-dk
siklik      gecirme  fark edilen  onceden yakalanan  kayit disi gerceklesen  kisi-dk
  hic           0        0.00              0.00                   1.67         0
  yillik        1        1.26              0.00                   1.63        45
  uc-aylik      4        3.54              0.44                   1.22       180
  aylik        12        5.62              1.03                   0.59       540

sikligi artirmanin karsiligi (donem basina):
  hic -> yillik: +45 kisi-dk, +0.00 onceden yakalanan risk -> risk basina karsiligi yok
  yillik -> uc-aylik: +135 kisi-dk, +0.44 onceden yakalanan risk -> risk basina 310 kisi-dk
  uc-aylik -> aylik: +360 kisi-dk, +0.60 onceden yakalanan risk -> risk basina 602 kisi-dk

soru kumesi (14 risk x 3 soru = 42 yanit; R1 bu risk dusunuldu mu, R2 olasiligi ne kabul edilmisti, R3 tahmin tuttu mu):
  hic        kayitta 8.00/14 risk -> dogru 16.0, eksik 20.0, yanlis 6.0
  yillik     kayitta 9.26/14 risk -> dogru 27.8, eksik 9.5, yanlis 4.7
  uc-aylik   kayitta 11.54/14 risk -> dogru 34.6, eksik 4.9, yanlis 2.5
  aylik      kayitta 13.62/14 risk -> dogru 40.9, eksik 0.8, yanlis 0.4

Yıllık gözden geçirme dönem başına 1,26 risk fark ediyor ve bunların hiçbirini gerçekleşmeden önce yakalamıyor. Sayı sıfır olduğu için tesadüf değildir: gözden geçirme on ikinci ayda, gerçekleşme ise on iki aya yayılmış durumda, dolayısıyla fark etme neredeyse her zaman olaydan sonra geliyor. Yılda bir gözden geçirilen bir risk kaydı, sonraki dönem için doğru bir kayıt üretir ve içinde bulunulan dönem için hiçbir şey yapmaz.

Üç aylık sıklık 0,44, aylık sıklık 1,03 riski gerçekleşmeden önce yakalıyor; kayıt dışı kalıp gerçekleşen risk 1,67’den 0,59’a iniyor. Karşılığı ise artan bir eğridir: üç aylığa geçmek önceden yakalanan risk başına 310 kişi-dakika, aylığa geçmek 602 kişi-dakika. İkinci geçişin birim maliyeti birincinin iki katına yakın, çünkü kolay fark edilen riskler daha seyrek gözden geçirmede zaten yakalanmıştır. Sıklığı artırmanın getirisi azalır; nerede durulacağı, riskin etkisiyle kişi-dakikanın karşılaştırılabildiği bir soruya dönüşür.

Soru kümesi tablosu aynı eğriyi kaydın okunabilirliği tarafında gösteriyor. Kırk iki yanıttan gözden geçirilmeyen kayıtta 16’sı doğru, 20’si eksik, 6’sı yanlıştır. Yanlış olanlar “bu risk düşünüldü mü” sorusuna verilen yanıtlardır: kayıt dışı bir risk için verilecek yanıt “hayır” olur ve bu yanıt doğru görünür, çünkü kayıt gerçekten sessizdir. Aylık gözden geçirmede doğru yanıt 40,9’a çıkıyor. Kaydın değeri, içine bir kez yazılanla değil, ne sıklıkta yeniden okunduğuyla belirleniyor.

Özet

  • Gerçekleşen 2348 riskin 808’i, yani yüzde 34,4’ü kayıtta hiç yoktu; bir risk kaydının ilk ölçüsü içindekilerin doğruluğu değil, dışında kalanın büyüklüğüdür.
  • Kayıttaki bantlar sıralamayı korumadı: yüksek bandın tahmini 0,60 iken ölçülen oranı 0,49, düşük bandın tahmini 0,13 iken ölçülen oranı 0,30 çıktı.
  • İki büyük sapma zıt yönlüdür — kural-motoru-buyumesi 0,10 tahminle 0,50 ölçüldü, onbellek-tazelik-asimi 0,50 tahminle 0,15; bir kez yazılıp bırakılan tahmin yanlışlığını göstermez.
  • Yıllık gözden geçirme dönem başına 1,26 risk fark etti ve hiçbirini gerçekleşmeden önce yakalamadı; üç aylık 0,44, aylık 1,03 risk yakaladı ve kaçan risk 1,67’den 0,59’a indi.
  • Sıklığı artırmanın birim bedeli yükseliyor: önceden yakalanan risk başına 310 ve 602 kişi-dakika; soru kümesinde doğru yanıt 16’dan 40,9’a çıkarken yanlış yanıt 6’dan 0,4’e indi.

Sonraki Adım

Risk kaydı gerçekleşmemiş bir şeyi izler: olasılığı olan, henüz olmamış bir olay. Yanında bir kayıt daha durur ve o, çoktan gerçekleşmiş bir şeyi izler. Bir karar verildiğinde bazen bilerek eksik bir çözüm seçilir — hızlı çıkmak için, ya da doğru çözümün ne olduğu henüz bilinmediği için. O eksiklik sistemde kalır ve her değişiklikte biraz fazladan iş çıkarır. Bazen de eksiklik bilerek seçilmez, sonradan fark edilir. Sonraki ders bu iki durumu ayırır, aradaki farkın ölçülebilir olup olmadığını sınar ve eksikliğin değişiklik başına çıkardığı fazladan işi sayar.

İlerlemeni kaydetmek ve not almak için Giriş yap

Notlarım

Not almak için giriş yapmalısın.

Aramak için yazmaya başlayın.

↑↓ Esc gezin · aç · kapat