İçeriğe geç
academia.sh

Ders 04 / 18

İlişki Görselleştirme

1.101 abone çifti saçılım olarak kodlandığında işaret genişliği 1.600 ayırt edilebilir hücre bırakıyor ve noktaların 792'si, yani yüzde 71,9'u üst üste binip geri okunamaz oluyor; en yoğun hücrede 16 nokta var. Aynı çiftler ısı haritasına konduğunda tek bir nokta kaybolmuyor ama sayım kayboluyor: kaynaktaki 28 ayrı sayım değeri yedi renk basamağının altısına iniyor, 51 dolu hücrenin 37'si tek bir basamağa düşüyor ve ortalama oransal geri okuma hatası yüzde 280,9 çıkıyor. Basamaklar eşit aralık yerine eşit sayıda hücreye bölündüğünde aynı hata yüzde 15,7'ye iniyor. Her x için tek bir y veren çizgi ise bulutun ortalama 44,1 basamaklık açıklığını tek basamağa indiriyor.

İçindekiler

Birinci ders dört soru türünü kanallara bağlarken ilişki sorusunu ayırmıştı: bu soru iki değerin aynı anda geri okunmasını ister ve bunun için kanalın ikinci bir bağımsız kopyası gerekir. Yalnız konumun iki kopyası vardır, yatay ve düşey eksen. Bu ders o iki kopyayı kullanır.

Kullanılan çift, kurgu ağın doğal sorusudur: bir abonenin ilk dönem okuması onun genel düzeyini ne kadar iyi bildiriyor. İlişkinin gücü bir önceki kursta katsayıyla ölçüldü ve burada ne hesaplanır ne yorumlanır. Buradaki soru gösterime aittir: aynı ilişki üç biçimde kodlandığında okuyucunun eline ne geçiyor, ve nokta sayısı arttıkça ne kayboluyor.

  • GT20. İlişki sorusu iki konum kanalını aynı anda ister. Birinci dersin sonucudur ve burada girdi olarak kullanılır.
  • GT21. Çizilen nokta bir işarettir ve genişliği vardır. Tek bir noktanın değeri konum kanalından 100 basamakla okunur, ama iki nokta ancak işaret genişliğinden fazla ayrıldığında ayırt edilir. İşaret genişliği eksenin kırkta biri alındı.
  • GT22. Üst üste binen nokta geri okunmaz. Okuyucu bir hücreyi bir kez görür; ölçü, kaç noktanın ayrı bir hücrede kaldığıdır.
  • GT23. Isı haritası nokta kaybetmez, sayım kaybeder. Her nokta bir hücrede sayılır, ama sayım renk basamağına iner ve geri okunabilen düzey sayısı basamak sayısıyla sınırlıdır.
  • GT24. Renk basamağı sayımların dağılımına değil, konan sınıra göre bölünür. Sayımlar çarpıksa eşit aralıklı basamaklarda alt basamaklar dolar, üst basamaklar boş kalır.
  • GT25. Bir x için tek bir y veren gösterim, o x’teki açıklığı taşımaz. Çizginin geri okuttuğu sayı bir basamaktır; bulutun kapladığı basamak sayısı ayrı bir ölçüdür.

İki Konum Kanalı ve İşaret Genişliği

# iliski.py — MODELDIR: K03-K05'in kurgu olcum agi ayni tohumla uretilir.
# Iliski cifti: abonenin ilk donem okumasi ile ayni abonenin ortalamasi.
import math

TOHUM, HAM, M32 = 20260218, 1400, 0xFFFFFFFF
DONEM = ["2026-01", "2026-02", "2026-03"]
BOLGE = [("kuzey", 0.28, 21), ("guney", 0.22, 17), ("dogu", 0.18, 26),
         ("bati", 0.14, 14), ("merkez", 0.18, 23)]


def uretec(t):
    x = ((t ^ (t >> 16)) * 2246822507) & M32
    x = ((x ^ (x >> 13)) * 3266489909) & M32
    s = [(x ^ (x >> 16)) & M32]

    def sonraki():
        s[0] = (s[0] * 1664525 + 1013904223) & M32
        return s[0] / 4294967296
    return sonraki


def ayrik(u, w):
    t = 0.0
    for i, x in enumerate(w):
        t += x
        if u < t:
            return i
    return len(w) - 1


_k, _e = [], []
for i in range(HAM):
    r = uretec(TOHUM + i)
    b = BOLGE[ayrik(r(), [x[1] for x in BOLGE])]
    ayrik(r(), [0.06, 0.24, 0.30, 0.24, 0.11, 0.05])
    ayrik(r(), [0.08, 0.14, 0.27, 0.34, 0.17])
    (_e if r() < 0.046 else _k).append(
        {"abone_no": 10001 + i, "bolge": b[0], "taban": b[2]})
GECERLI = {a["abone_no"] for a in _k}

OKUMA = []
for a in _k + _e:
    r = uretec(TOHUM + 7000 + a["abone_no"])
    for d in range(ayrik(r(), [0.05, 0.12, 0.21, 0.62])):
        t = 0.0 if r() < 0.038 else math.floor(
            a["taban"] * math.exp((r() + r() + r() - 1.5) * 0.62)
            * (1 - d * 0.05) * 100 + 0.5) / 100
        if a["abone_no"] not in GECERLI:
            r()
            continue
        OKUMA.append({"abone_no": a["abone_no"], "bolge": a["bolge"],
                      "donem": DONEM[d], "tuketim_m3": t})
        r()

from collections import defaultdict

# Ilki abonenin ilk donem okumasi, ikincisi ayni abonenin butun donemlerinin
# ortalamasi. En az iki okumasi olan aboneler alinir.
_d = defaultdict(list)
for o in OKUMA:
    _d[o["abone_no"]].append((o["donem"], o["tuketim_m3"]))
CIFT = []
for _no in sorted(_d):
    v = sorted(_d[_no])
    if len(v) >= 2:
        CIFT.append((v[0][1], sum(x for _, x in v) / len(v)))

# Iki nokta ancak isaret genisliginden fazla ayrildiginda ayirt edilir.
# Cizilen nokta bir isarettir ve genisligi vardir; isaret genisligi eksenin
# kirkta biri alindi. Tek bir noktanin degeri ise konum kanalindan, 100
# basamakla okunur.
COZ_KONUM, ISARET = 100, 40


def yuvarla_on(x):
    return (int(x) // 10 + 1) * 10


EKSEN_X = yuvarla_on(max(a for a, _ in CIFT))
EKSEN_Y = yuvarla_on(max(b for _, b in CIFT))


def hucre(p):
    return (min(ISARET - 1, int(ISARET * p[0] / EKSEN_X)),
            min(ISARET - 1, int(ISARET * p[1] / EKSEN_Y)))


# Alt kume secimi tohumdan gelir: cift dizisi bir kez karistirilir, sonra
# bastan alinir. Boylece her boyut ayni siranin onekidir.
_r = uretec(TOHUM + 404)
SIRA = list(range(len(CIFT)))
for i in range(len(SIRA) - 1, 0, -1):
    j = int(_r() * (i + 1))
    SIRA[i], SIRA[j] = SIRA[j], SIRA[i]
KARISIK = [CIFT[i] for i in SIRA]

print(f"kurgu iliski kumesi: {len(CIFT)} abone cifti "
      f"(ilk donem okumasi, abonenin ortalamasi)")
print(f"eksenler 0-{EKSEN_X} ve 0-{EKSEN_Y} m3; konum cozunurlugu {COZ_KONUM} "
      f"basamak, isaret genisligi eksenin 1/{ISARET}'i")
print(f"duzlem {ISARET}x{ISARET} = {ISARET * ISARET} ayirt edilebilir hucre")
kurgu iliski kumesi: 1101 abone cifti (ilk donem okumasi, abonenin ortalamasi)
eksenler 0-60 ve 0-50 m3; konum cozunurlugu 100 basamak, isaret genisligi eksenin 1/40'i
duzlem 40x40 = 1600 ayirt edilebilir hucre

İki çözünürlük sayısı yan yana duruyor ve ikisi aynı şey değil. Tek bir noktanın değeri konum kanalından okunur ve eksende 100 basamak vardır; birinci dersin sayısıdır. Ama iki noktanın ayrı iki nokta olarak görülmesi için aralarındaki uzaklığın işaretin kendi genişliğini aşması gerekir. Çizilen nokta bir matematiksel nokta değildir; sayfada bir yer kaplar ve o yer eksenin kırkta biri alındı. Düzlem bu yüzden 100 çarpı 100 değil, 40 çarpı 40 ayırt edilebilir hücreye bölünür ve 1.600 hücreye 1.101 nokta konacaktır.

Nokta Sayısı Arttıkça

# sacilim.py — nokta sayisi arttikca kac nokta ayri bir hucrede kaliyor.
# Ust uste binen nokta geri okunmaz: okuyucu hucreyi bir kez gorur.
print(f"{'nokta':>7s}{'dolu hucre':>12s}{'gizlenen':>10s}{'gizlenen %':>12s}"
      f"{'en yogun hucre':>16s}")
for n in (100, 250, 500, 800, len(KARISIK)):
    s = defaultdict(int)
    for p in KARISIK[:n]:
        s[hucre(p)] += 1
    print(f"{n:7d}{len(s):12d}{n - len(s):10d}{100 * (n - len(s)) / n:11.1f}%"
          f"{max(s.values()):16d}")
  nokta  dolu hucre  gizlenen  gizlenen %  en yogun hucre
    100          85        15       15.0%               3
    250         161        89       35.6%               5
    500         232       268       53.6%               9
    800         266       534       66.8%              12
   1101         309       792       71.9%              16

Düzlemde 1.600 hücre var ve noktalar 1.101 tane. Boş yer bol görünüyor, ama 1.101 nokta yalnız 309 hücreye düşüyor ve 792 nokta, yani yüzde 71,9’u, üzerine başka bir nokta binmiş durumda. Sebep, noktaların düzleme eşit dağılmamasıdır: ilişkinin olduğu yerde nokta yığılır ve tam da en çok bilgi taşıyan bölge en okunamaz bölge olur. En yoğun hücrede 16 nokta üst üste duruyor ve okuyucu için o hücre tek bir noktadan farksız.

Sütunun nasıl büyüdüğü ayrıca kaydedilmeye değer. Yüz noktada gizlenen oran yüzde 15,0; iki yüz elli noktada yüzde 35,6; beş yüzde yüzde 53,6. Nokta sayısı on bir katına çıkarken dolu hücre sayısı yalnız 85’ten 309’a, yani üç buçuk katına çıkıyor. Saçılımın taşıdığı bilgi nokta sayısıyla değil, dolu hücre sayısıyla büyür ve bu sayının bir tavanı vardır: 1.600.

Isı Haritası ve Basamak Sınırı Kararı

# isi_haritasi.py — ayni cift kumesi kaba araliklara bolunur, her hucrenin
# sayimi renk basamagina cevrilir ve geri okunur. Renk bir ad degil, bir
# basamak numarasidir; basamak sayisi birinci dersteki gibi 7.
NX, NY, BASAMAK = 12, 10, 7
GX, GY = EKSEN_X / NX, EKSEN_Y / NY
SAYIM = defaultdict(int)
for a, b in CIFT:
    SAYIM[(min(NX - 1, int(a / GX)), min(NY - 1, int(b / GY)))] += 1
ENC = max(SAYIM.values())


def kodla_renk(c):
    return min(BASAMAK - 1, int(BASAMAK * c / ENC))


def coz_renk(b):
    return (b + 0.5) * ENC / BASAMAK


print(f"{NX}x{NY} aralik ({GX:.0f}x{GY:.0f} m3), en yogun hucre {ENC} nokta, "
      f"{BASAMAK} renk basamagi")
for j in range(NY - 1, -1, -1):
    print(f"{(j + 1) * GY:5.0f} |" + "".join(
        str(kodla_renk(SAYIM[(i, j)])) if SAYIM[(i, j)] else "." for i in range(NX)))
print("      +" + "-" * NX + f"  x ekseni 0-{EKSEN_X} m3")

dolu = [c for c in SAYIM.values() if c > 0]
duzey_k = len(set(dolu))
duzey_g = len({kodla_renk(c) for c in dolu})
ora = sum(abs(coz_renk(kodla_renk(c)) - c) / c for c in dolu) / len(dolu)
print(f"dolu hucre {len(dolu)}, hicbir nokta kaybolmadi: "
      f"{sum(dolu)} = {len(CIFT)}")
print(f"kaynakta {duzey_k} ayri sayim degeri var, geri okunan duzey {duzey_g}"
      f"/{BASAMAK}; ortalama oransal geri okuma hatasi {100 * ora:.1f}%")
print("basamak dolulugu: " + ", ".join(
    f"{b}:{sum(1 for c in dolu if kodla_renk(c) == b)}" for b in range(BASAMAK)))

# Ikinci karar: basamaklar esit araliklara degil, esit sayida hucreye bolunur.
# Sinirlar sirali sayimlardan gelir, her basamagin temsil degeri kendi
# hucrelerinin ortancasidir.
_s = sorted(dolu)
SINIR = [_s[round(len(_s) * k / BASAMAK)] for k in range(1, BASAMAK)]


def kodla_sira(c):
    b = 0
    while b < BASAMAK - 1 and c >= SINIR[b]:
        b += 1
    return b


TEMSIL = []
for b in range(BASAMAK):
    g = sorted(c for c in dolu if kodla_sira(c) == b)
    TEMSIL.append(g[len(g) // 2] if g else 0)
ora2 = sum(abs(TEMSIL[kodla_sira(c)] - c) / c for c in dolu) / len(dolu)
print(f"esit sayida hucre karari: geri okunan duzey "
      f"{len({kodla_sira(c) for c in dolu})}/{BASAMAK}, "
      f"ortalama oransal hata {100 * ora2:.1f}%")
print("basamak dolulugu: " + ", ".join(
    f"{b}:{sum(1 for c in dolu if kodla_sira(c) == b)}" for b in range(BASAMAK)))
12x10 aralik (5x5 m3), en yogun hucre 140 nokta, 7 renk basamagi
   50 |............
   45 |........0...
   40 |...000.000..
   35 |...00000000.
   30 |..00121000..
   25 |..044310....
   20 |004641000...
   15 |0142000.....
   10 |00000.......
    5 |.0..........
      +------------  x ekseni 0-60 m3
dolu hucre 51, hicbir nokta kaybolmadi: 1101 = 1101
kaynakta 28 ayri sayim degeri var, geri okunan duzey 6/7; ortalama oransal geri okuma hatasi 280.9%
basamak dolulugu: 0:37, 1:5, 2:2, 3:1, 4:5, 5:0, 6:1
esit sayida hucre karari: geri okunan duzey 6/7, ortalama oransal hata 15.7%
basamak dolulugu: 0:0, 1:13, 2:7, 3:8, 4:8, 5:8, 6:7

Isı haritası saçılımın kaybettiği şeyi kaybetmiyor: 1.101 noktanın hepsi bir hücrede sayıldı ve toplam birebir tutuyor. Kaybettiği başka bir şey — sayımın kendisi. Kaynakta 28 ayrı sayım değeri var; renk basamağı bunları yediye, gerçekte de altıya indiriyor.

Basamak dolulukları GT24’ün doğrudan kanıtı. Eşit aralıklı bölme, en yoğun hücrenin 140 noktasını ölçü alır ve 51 dolu hücrenin 37’sini tek bir basamağa, en alttakine yığar. O basamağın orta değeri 10 noktadır; içinde tek noktalı hücreler de vardır. Ortalama oransal geri okuma hatası bu yüzden yüzde 280,9 çıkar ve okuyucu düzlemin çoğunu tek bir düzey olarak görür — düzlemdeki sıfırların yanında sıralanan sıfırlar bunu gösteriyor.

İkinci karar aynı veriyi aynı yedi basamakla kodluyor, yalnız sınırları başka yere koyuyor: basamaklar eşit aralığa değil, eşit sayıda hücreye bölünüyor. Doluluk dengeleniyor ve ortalama oransal hata yüzde 15,7’ye, on sekizde birine iniyor. Bedeli vardır ve yazılmalıdır: eşit sayıda hücreye bölünmüş bir basamak dizisi büyüklüğü değil sırayı taşır. Birinci kararla iki hücrenin basamak farkı kaç nokta olduğunu bildirir, ikinci kararla yalnız hangisinin daha kalabalık olduğunu. Aynı veri, aynı gösterim, iki savunulabilir karar ve on sekiz kat fark.

Çizginin Taşımadığı

# cizgi.py — ucuncu gosterim: her x icin tek bir y veren bir cizgi. Cizginin
# katsayisi M26/K05'te hesaplandi ve burada ne hesaplanir ne yorumlanir;
# olculen tek sey, tek bir y'nin o x'te ne kadarini tasidigi. Aciklik konum
# kanalinin basamagi cinsinden yazilir (eksen 100 basamaga bolunmus).
print(f"{'x araligi':>12s}{'nokta':>7s}{'y en kucuk':>12s}{'y en buyuk':>12s}"
      f"{'aciklik basamak':>17s}")
bas = []
for i in range(NX):
    ys = [b for a, b in CIFT if min(NX - 1, int(a / GX)) == i]
    if len(ys) < 20:
        continue
    n = round(COZ_KONUM * (max(ys) - min(ys)) / EKSEN_Y)
    bas.append(n)
    print(f"{i * GX:6.0f}-{(i + 1) * GX:<5.0f}{len(ys):7d}{min(ys):12.2f}"
          f"{max(ys):12.2f}{n:17d}")
print(f"cizgi her x icin 1 basamak veriyor; bulut ortalama "
      f"{sum(bas) / len(bas):.1f} basamak kapliyor")
   x araligi  nokta  y en kucuk  y en buyuk  aciklik basamak
     0-5         36        5.82       19.04               26
     5-10        30        3.49       19.43               32
    10-15       205        5.46       26.61               42
    15-20       295        6.57       35.66               58
    20-25       235        7.84       38.13               61
    25-30       154       12.01       35.71               47
    30-35        84       13.91       33.52               39
    35-40        34       17.53       38.84               43
    40-45        20       18.87       43.48               49
cizgi her x icin 1 basamak veriyor; bulut ortalama 44.1 basamak kapliyor

Üçüncü gösterim en az yer kaplayanıdır ve en çok şeyi atar. Bir çizgi her x için tek bir y verir; o değer konum kanalının tek bir basamağıdır. Aynı x aralığında gözlemler ortalama 44,1 basamak kaplıyor, yani çizginin geri okuttuğu sayı bulutun düşey açıklığının kırk dörtte biri kadar bir yer tutuyor. 15–20 m³ aralığında 295 abone var ve ortalamaları 6,57 ile 35,66 m³ arasında değişiyor; çizgi bu aralığa tek bir sayı koyar.

Bu, çizgiye karşı bir itiraz değildir. Çizgi zaten açıklığı atmak için vardır ve rapor bir eğilim soruyorsa doğru gösterimdir. Kaydedilecek şey, atılan şeyin sayılabilir olmasıdır: çizginin yanına açıklık yazılmadığında okuyucu, kırk dört basamaklık bir bulutu bir basamak sanır.

Özet

  • İlişki iki konum kanalıyla kodlanır; tek noktanın değeri 100 basamakla okunur, ama iki noktanın ayrılması işaret genişliğine bağlıdır ve düzlem 40 çarpı 40 hücreye iner.
  • 1.101 nokta yalnız 309 hücreye düşer: 792 nokta, yüzde 71,9’u, üst üste biner ve en yoğun hücrede 16 nokta durur. Saçılımın taşıdığı bilgi nokta sayısıyla değil dolu hücre sayısıyla büyür.
  • Isı haritası hiçbir noktayı kaybetmez ama sayımı kaybeder: kaynaktaki 28 ayrı sayım değeri yedi basamağın altısına iner, 51 dolu hücrenin 37’si tek basamağa düşer, oransal hata yüzde 280,9.
  • Basamak sınırı eşit aralık yerine eşit sayıda hücreye konduğunda aynı hata yüzde 15,7’ye iner; bedeli, basamağın artık büyüklüğü değil sırayı taşımasıdır.
  • Her x için tek bir y veren çizgi, ortalama 44,1 basamaklık bir açıklığı tek basamağa indirir; açıklık yazılmadığında okuyucu bulutu çizgi sanır.

Sonraki Adım

Dört derste dört kanal ölçüldü: konum, uzunluk, alan ve renk basamağı — hepsi tek bir anlık görüntü üzerinde. Beş bölgenin ortalaması bir andaydı, kuzeyin dağılımı bir dönemin toplamıydı, çapraz tablo bir kesitti, saçılımın iki ekseni de aynı zamana aitti. Eksenlerden biri zaman olduğunda kanalın taşıdığı şey değişir: okuyucu artık bir değer değil bir değişim okur, ve değişimin kendisi ölçülmemiş bir sayıdır. Sonraki ders o eksene geçer ve eğimin geri okunmasını ölçer — aynı dizi iki eksen ölçeğiyle kodlandığında geri okunan eğim ne oluyor, mevsimsel bileşen ayrılmadan eğilim okunabiliyor mu.

İ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