---
title: 'Mahremiyet Koruyan Öğrenme'
source: 'https://academia.sh/tr/kurslar/model-etik-ve-yorum/mahremiyet-koruyan-ogrenme'
course: 'Model Değerlendirme, Yorumlanabilirlik ve Etik'
language: tr
updated: '2026-08-17T18:10:13+00:00'
license: 'CC BY-SA 4.0'
---

# Mahremiyet Koruyan Öğrenme

Modelin kendi eğitim kayıtları hakkında ne söylediğinin savunma tarafından sayılması: abone numarası silinmiş 1.260 satırlık tabloda dört alt grup ekseni 72 birleşim üretiyor ve 6 kayıt tek başına kalıyor, altıncı alan eklendiğinde bu sayı 1.242'ye, yani 0,9857'ye çıkıyor. Tek bir eğitim kaydının çıkarılması doğrusal modelin çıktısını en çok 0,0313 oynatıyor ve iki tahmini değiştiriyor; aynı kayıt hücre tablosuna dayanan modelde çıktıyı 0,7778 oynatıyor ve 14 tahmini değiştiriyor, çünkü 66 hücrenin 13'ünde tek bir kayıt var. Gürültü on düzeyde süpürüldüğünde doğrusal modelin izini örtmek 0,04 gürültü ve 0,0022 doğruluk istiyor, hücre modelininki 0,80 gürültü ve tabanın 0,1669 altına düşmek istiyor.

İki derste ölçülen şey modelin dışarıya, yani üzerine uygulandığı abonelere ne yaptığıydı.
Modelin **içeriye**, yani üzerinde eğitildiği kayıtlara doğru ne sızdırdığı sorulmadı. Eğitim
kümesindeki bir abone tabloya girdiğinde modelin çıktısı değişiyorsa, o çıktı o abone hakkında
bir şey taşıyor demektir. Taşıdığı şeyin büyüklüğü ölçülebilir.

Bu ders o ölçümü yapar ve iki soruyla sınırlıdır. Birincisi: bir tablodan abone numarasını
silmek o aboneyi görünmez kılar mı. İkincisi: tek bir kaydın çıkarılması modelin çıktısını ne
kadar oynatır, ve o oynamayı örtmenin doğruluktan bedeli nedir. Kişisel verinin ne olduğu,
saklama süresi ve analizin sınırı M25/K05 ile M26/K01'in Verinin Yapısı konusunda ölçülmüştü;
tekrarlanmaz. Burada ölçülen şey yalnız **modelin** ve **tablonun** kendi davranışıdır.

- **ME17.** Küme, bölme, model ve alt grup tanımları önceki iki dersten aynen sürer: 756 satırlık
  eğitim kümesi, 504 abonelik ayrılmış küme, **on üç alt grup**, taban 0,7857.
- **ME18.** Tablo **kimliksizleştirilmiş** kabul edilir: abone numarası sütunu yoktur. Geriye
  kalan alanlar ölçümden ve abone kaydından gelen sıradan alanlardır.
- **ME19.** Birleştirilebilirlik ölçüsü **kaç kaydın kendi alan birleşiminde tek kaldığıdır**.
  Bu bir kimliklendirme yordamı değil, tablonun kendi üzerinde yapılan bir sayımdır.
- **ME20.** İkinci bir model karşılaştırma için kurulur: **hücre tablosu**. Dört alt grup ekseni
  bir hücre verir, hücredeki şüpheli oranı çıktıdır. Küçük ve zayıf bir modeldir; buradaki işi
  yapısı gereği az kayda dayanan bir çıktının nasıl davrandığını göstermektir.
- **ME21.** **Kayıt duyarlılığı**, tek bir eğitim kaydı çıkarıldığında modelin ayrılmış kümedeki
  çıktısında görülen en büyük oynamadır. Doğrusal modelde her ölçüm bir yeniden eğitim istediği
  için **on altı kayıt** örneklenir; hücre modelinde 756 kaydın hepsi tam olarak hesaplanır.
- **ME22.** **Gürültü ekleme**, yayımlanan çıktıya eksi ve artı yönde eşit olasılıkla bir sayı
  eklemektir. Gürültü ölçeği on düzeyde süpürülür ve her düzeyde yirmi kez çekilip ortalanır.
- **ME23.** "Gürültünün üstünde kalan kayıt", izi gürültü ölçeğinin alabileceği en büyük değeri
  aşan kayıttır. Sayı düştükçe tek tek kayıtların çıktıdaki payı gürültünün içinde kalır.
- **ME24.** Ölçüm bütünüyle savunma tarafındadır: hiçbir çıkarım yordamı kurulmaz, yalnız
  korunacak büyüklükler sayılır.

## Numarayı Silmek Ne Siler

İlk soru modelden önce tabloya sorulur. Abone numarası silindiğinde geriye kalan alanların
birleşimi kaç kaydı yalnız bırakıyor. Aşağıdaki blok alanları teker teker ekliyor ve her adımda
kaç ayrı birleşim oluştuğunu, kaç kaydın o birleşimde tek kaldığını sayıyor.

```python
# mahremiyet.py — MODELDIR. Ayni KURGU abone tablosu, ayni tohum ve ayni bolme;
# olculen sey savunma tarafindadir: tablonun ve modelin kendi davranisi.
import math
import statistics

TOHUM, HAM, M32 = 20260218, 1400, 0xFFFFFFFF
BOLGE = [("kuzey", 0.28, 21, 0.00), ("guney", 0.22, 17, -0.10),
         ("dogu", 0.18, 26, 0.30), ("bati", 0.14, 14, -0.05),
         ("merkez", 0.18, 23, 0.05)]


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


ABONE, VERI = [], []
for i in range(HAM):
    r = uretec(TOHUM + i)
    b = BOLGE[ayrik(r(), [x[1] for x in BOLGE])]
    hane = 1 + ayrik(r(), [0.06, 0.24, 0.30, 0.24, 0.11, 0.05])
    memnun = 1 + ayrik(r(), [0.08, 0.14, 0.27, 0.34, 0.17])
    if r() >= 0.046:
        ABONE.append({"no": 10001 + i, "bolge": b, "hane": hane, "memnuniyet": memnun})
for k in ABONE:
    r, v = uretec(TOHUM + 7000 + k["no"]), []
    for d in range(ayrik(r(), [0.05, 0.12, 0.21, 0.62])):
        v.append(0.0 if r() < 0.038 else math.floor(
            k["bolge"][2] * math.exp((r() + r() + r() - 1.5) * 0.62)
            * (1 - d * 0.05) * 100 + 0.5) / 100)
        r()
    if not v:
        continue
    ort, oyn, r = sum(v) / len(v), max(v) - min(v), uretec(TOHUM + 51000 + k["no"])
    z = (0.052 * (ort - 20) + 0.85 * (min(v) == 0.0) + 0.026 * oyn
         + 0.24 * (k["hane"] >= 5) - 0.20 * (k["memnuniyet"] >= 4) + k["bolge"][3]
         + 0.9 * (k["no"] - 10001) / 1399 + (r() + r() + r() - 1.5) * 1.30)
    x = {"hane": k["hane"], "memnuniyet": k["memnuniyet"], "donem": len(v),
         "ort_tuketim": round(ort, 2), "oynaklik": round(oyn, 2), "il": k["bolge"][0],
         "sifir_okuma": int(min(v) == 0.0), "supheli": int(z > 1.35)}
    x["kisi_basi"] = round(x["ort_tuketim"] / x["hane"], 3)
    for b in BOLGE:
        x["b_" + b[0]] = int(k["bolge"][0] == b[0])
    VERI.append(x)


def karistir(veri, tohum):
    r, s = uretec(tohum), list(range(len(veri)))
    for i in range(len(s) - 1, 0, -1):
        j = int(r() * (i + 1))
        s[i], s[j] = s[j], s[i]
    return [veri[i] for i in s]


K = karistir(VERI, TOHUM + 90000)
EGT, AYR = K[:756], K[756:]
ALAN = ["ort_tuketim", "oynaklik", "hane", "memnuniyet", "donem", "sifir_okuma",
        "kisi_basi", "b_kuzey", "b_guney", "b_dogu", "b_bati", "b_merkez"]
ORT = {a: statistics.fmean(x[a] for x in EGT) for a in ALAN}
SAP = {a: max(1e-9, statistics.pstdev([x[a] for x in EGT])) for a in ALAN}


def olcekli(x):
    return [1.0] + [(x[a] - ORT[a]) / SAP[a] for a in ALAN]


def sikistir(z):
    if z >= 0:
        return 1.0 / (1.0 + math.exp(-z)) if z < 700 else 1.0
    e = math.exp(z) if z > -700 else 0.0
    return e / (1.0 + e)


def egit(kume, etiket):                  # MODELDIR: dogrusal model, egim inisi
    X = [olcekli(x) for x in kume]
    Y = [x[etiket] for x in kume]
    w = [0.0] * len(X[0])
    for _ in range(200):
        g = [0.0] * len(w)
        for i in range(len(X)):
            h = sikistir(sum(w[j] * X[i][j] for j in range(len(w)))) - Y[i]
            for j in range(len(w)):
                g[j] += h * X[i][j]
        for j in range(len(w)):
            w[j] -= 0.3 * g[j] / len(X)
    return w


def olasilik(w, x):
    return sikistir(sum(a * b for a, b in zip(w, olcekli(x))))


from collections import Counter, defaultdict


def gruplar(x):
    t = 10 if x["ort_tuketim"] <= 10 else 25 if x["ort_tuketim"] <= 25 else 40
    return ["bolge " + x["il"], "tarife %d" % t,
            "hane " + ("1-2" if x["hane"] <= 2 else "3-4" if x["hane"] <= 4 else "5+"),
            "okuma " + ("az" if x["donem"] <= 2 else "tam")]


ALANLAR = ["bolge", "tarife basamagi", "hane buyuklugu", "okuma sayisi",
           "memnuniyet", "ortalama tuketim"]


def anahtar(x, k):                       # kimliksizlestirilmis kaydin ilk k alani
    return tuple((gruplar(x) + [x["memnuniyet"], x["ort_tuketim"]])[:k])


print(f"kayit {len(VERI)}, abone numarasi tabloda yok, bakilan alt grup "
      f"{len({g for x in AYR for g in gruplar(x)})}")
print(f"{'alan':>5} {'eklenen alan':<18}{'birlesim':>10}{'tek kalan kayit':>17}{'oran':>9}")
for k in range(1, 7):
    c = Counter(anahtar(x, k) for x in VERI)
    tek = sum(1 for x in VERI if c[anahtar(x, k)] == 1)
    print(f"{k:>5} {ALANLAR[k - 1]:<18}{len(c):>10}{tek:>17}{tek / len(VERI):>9.4f}")
```

```
kayit 1260, abone numarasi tabloda yok, bakilan alt grup 13
 alan eklenen alan        birlesim  tek kalan kayit     oran
    1 bolge                      5                0   0.0000
    2 tarife basamagi           15                1   0.0008
    3 hane buyuklugu            41                4   0.0032
    4 okuma sayisi              72                6   0.0048
    5 memnuniyet               247               69   0.0548
    6 ortalama tuketim        1251             1242   0.9857
```

İlk dört satır kursun alt grup eksenleridir ve kaba alanlardır: 1.260 kayıt yalnız 72 birleşime
düşüyor, tek kalan kayıt 6. Beşinci alan bu sayıyı 69'a çıkarıyor. Altıncı alan, yani virgülden
sonra iki basamak taşıyan ortalama tüketim, tabloyu tek adımda 1.251 birleşime bölüyor ve
kayıtların **0,9857'si** kendi birleşiminde tek başına kalıyor.

Okunacak şey son satırın büyüklüğü değil, dördüncü satırdan altıncıya geçişteki sıçramadır.
Kimliksizleştirme bir sütunu siler; birleştirilebilirliği silmez. Bir tablodaki alanların **sayısı
ve çözünürlüğü**, o tablonun ne kadar kimliksiz olduğunu numaranın varlığından daha çok belirler.
Sürekli bir alanı basamağa yuvarlamak bu sayıyı doğrudan düşürür ve bunun bedeli modelin
gördüğü ayrıntıdır.

## Tek Bir Kaydın Bıraktığı İz

İkinci soru modele sorulur. Bir eğitim kaydı çıkarılıp model yeniden eğitildiğinde ayrılmış
kümedeki çıktı ne kadar oynuyor. Aşağıdaki blok bunu iki modelde ölçüyor: on iki sütunlu doğrusal
model ve dört eksenin verdiği hücre tablosu. İkinci model için ölçüm tam olarak yapılabilir,
çünkü bir kaydın çıkarılması yalnız kendi hücresinin oranını değiştirir.

```python
def hucre(x):
    return tuple(gruplar(x))


SAY = defaultdict(lambda: [0, 0])        # MODELDIR: hucre tablosu, hucre orani soyler
for x in EGT:
    h = SAY[hucre(x)]
    h[0], h[1] = h[0] + 1, h[1] + x["supheli"]
KUR = sum(x["supheli"] for x in EGT) / len(EGT)
AYR_H = Counter(hucre(x) for x in AYR)


def horan(x):
    v = SAY.get(hucre(x))
    return KUR if v is None else v[1] / v[0]


D, hdeg = [], 0
for x in EGT:
    n, k = SAY[hucre(x)]
    q = (k - x["supheli"]) / (n - 1) if n > 1 else KUR
    D.append(abs(k / n - q))
    if (k / n > 0.5) != (q > 0.5):
        hdeg = max(hdeg, AYR_H[hucre(x)])
D.sort(reverse=True)
W = egit(EGT, "supheli")
P0 = [olasilik(W, x) for x in AYR]
r = uretec(TOHUM + 71000)
IZ = []
for _ in range(16):
    x = EGT[int(r() * len(EGT))]
    w = egit([y for y in EGT if y is not x], "supheli")
    P1 = [olasilik(w, y) for y in AYR]
    IZ.append((max(abs(a - b) for a, b in zip(P0, P1)),
               sum((a > 0.5) != (b > 0.5) for a, b in zip(P0, P1))))
IZ.sort(reverse=True)
tabAY = sum(x["supheli"] == 0 for x in AYR) / len(AYR)
print(f"hucre {len(SAY)}, en kucuk hucre {min(v[0] for v in SAY.values())} kayit, "
      f"tek kayitlik hucre {sum(1 for v in SAY.values() if v[0] == 1)}, "
      f"iki ve alti {sum(1 for v in SAY.values() if v[0] <= 2)}")
print(f"taban {tabAY:.4f}, birakilan kayit {len(IZ)} (dogrusal), {len(D)} (hucre)")
print(f"\n{'model':<22}{'dogruluk':>10}{'en buyuk iz':>13}{'ortanca iz':>12}"
      f"{'degisen tahmin':>16}")
print(f"{'dogrusal model':<22}"
      f"{sum((p > 0.5) == x['supheli'] for p, x in zip(P0, AYR)) / len(AYR):>10.4f}"
      f"{IZ[0][0]:>13.4f}{IZ[len(IZ) // 2][0]:>12.4f}{max(v[1] for v in IZ):>16}")
print(f"{'hucre modeli':<22}"
      f"{sum((horan(x) > 0.5) == x['supheli'] for x in AYR) / len(AYR):>10.4f}"
      f"{D[0]:>13.4f}{D[len(D) // 2]:>12.4f}{hdeg:>16}")
```

```
hucre 66, en kucuk hucre 1 kayit, tek kayitlik hucre 13, iki ve alti 22
taban 0.7857, birakilan kayit 16 (dogrusal), 756 (hucre)

model                   dogruluk  en buyuk iz  ortanca iz  degisen tahmin
dogrusal model            0.8194       0.0313      0.0030               2
hucre modeli              0.7917       0.7778      0.0074              14
```

İki satır arasındaki fark yirmi beş katı aşıyor. Doğrusal modelde bir kaydın çıkarılması 504
abonenin hiçbirinde olasılığı 0,0313'ten fazla oynatmıyor ve en fazla iki tahmini değiştiriyor;
ortanca iz 0,0030, yani kayıtların yarısından fazlası çıktıda neredeyse hiç iz bırakmıyor. Bunun
sebebi modelin her çıktısını 756 kaydın **hepsinden** üretmesidir; tek bir satırın payı on üç
ağırlığa dağılıyor.

Hücre modelinde aynı ölçüm 0,7778 veriyor. Sebebi ikinci satırın başındaki sayılardır: 66
hücrenin 13'ünde tek bir kayıt var, 22'sinde iki ya da daha az. Tek kayıtlık bir hücrede
yayımlanan oran o tek kaydın etiketinin kendisidir. O hücrenin kararı çevrildiğinde ayrılmış
kümede 14 abonenin tahmini değişiyor. Kural buradan çıkar ve modelden bağımsızdır: **bir çıktı ne
kadar az kayda dayanıyorsa o kayıtlar o çıktıda o kadar açıktadır.** Aynı sayı önceki dersteki
küçük alt grup uyarısının öbür yüzüdür — ölçülemeyecek kadar küçük bir alt grup, aynı zamanda
gizlenemeyecek kadar küçük bir alt gruptur.

## Gürültünün Bedeli

İzi küçültmenin doğrudan yolu yayımlanan çıktıya gürültü eklemektir. Gürültü izi örter ama
doğruluğu da götürür. Aşağıdaki süpürme on gürültü düzeyinde iki modelin doğruluğunu ve o düzeyin
üstünde iz bırakan kayıt sayısını yan yana basıyor.

```python
print(f"\n{'gurultu':>8}{'dogrusal dogruluk':>19}{'hucre dogruluk':>16}"
      f"{'dogrusal ustte':>16}{'hucre ustte':>13}")
for b in (0.00, 0.02, 0.04, 0.08, 0.12, 0.20, 0.30, 0.45, 0.60, 0.80):
    dl = hl = 0.0
    for t in range(20):                  # gurultu yirmi kez cekilir, ortalama basilir
        rd = uretec(TOHUM + 74000 + t * 13)
        dl += sum(((p + b * (2 * rd() - 1)) > 0.5) == x["supheli"]
                  for p, x in zip(P0, AYR)) / len(AYR)
        rh = uretec(TOHUM + 75000 + t * 13)
        gp = {h: min(1.0, max(0.0, v[1] / v[0] + b * (2 * rh() - 1)))
              for h, v in SAY.items()}
        hl += sum((gp.get(hucre(x), KUR) > 0.5) == x["supheli"] for x in AYR) / len(AYR)
    print(f"{b:>8.2f}{dl / 20:>19.4f}{hl / 20:>16.4f}"
          f"{sum(1 for v, _ in IZ if v > b):>16}{sum(1 for v in D if v > b):>13}")
```

```

 gurultu  dogrusal dogruluk  hucre dogruluk  dogrusal ustte  hucre ustte
    0.00             0.8194          0.7917              16          679
    0.02             0.8184          0.7792               1          246
    0.04             0.8172          0.7792               0          140
    0.08             0.8151          0.7792               0           59
    0.12             0.8126          0.7780               0           34
    0.20             0.8043          0.7696               0           25
    0.30             0.7910          0.7584               0           12
    0.45             0.7560          0.7265               0           11
    0.60             0.6908          0.6779               0            1
    0.80             0.6436          0.6188               0            0
```

Doğrusal model için hesap ucuzdur. On altı kaydın hiçbiri 0,04 gürültünün üstünde iz bırakmıyor
ve o düzeyde doğruluk 0,8194'ten 0,8172'ye, yani 0,0022 iniyor — taban çizgisinin hâlâ 0,0315
üstünde. Gürültü ölçeği 0,30'a çıkarıldığında doğruluk 0,7910 ile tabanın hemen üstüne, 0,45'te
0,7560 ile tabanın altına düşüyor. Yani bedelin tamamı örtme işinden değil, gereğinden fazla
örtmekten geliyor.

Hücre modelinde aynı hesap ödenemiyor. En büyük izi örtmek için gürültü ölçeğinin 0,80'e
çıkarılması gerekiyor; o düzeyde doğruluk 0,6188 ve taban çizgisinin **0,1669 altında**. Daha
kötüsü, model daha 0,02 gürültüde 0,7792'ye inip tabanın altına düşüyor — çünkü gürültüsüz hali
zaten tabanı yalnız 0,0060 geçiyordu. Elinde ödenecek pay olmayan bir model gürültünün bedelini
karşılayamaz.

İki sütun birlikte okunduğunda dersin sonucu çıkar. Mahremiyetin bedeli sabit bir sayı değildir;
**modelin yapısına ve taban çizgisinin ne kadar üstünde durduğuna bağlıdır.** Çıktısını çok
kayıttan üreten ve tabanı rahatça geçen bir model, tek tek kayıtların izini neredeyse bedelsiz
örtebilir. Çıktısını az kayıttan üreten ve tabana yapışık duran bir model, aynı korumayı ancak
kendini işe yaramaz hale getirerek satın alabilir.

## Özet

- Abone numarası silinmiş 1.260 satırlık tabloda dört kaba alan 72 birleşim üretiyor ve 6 kayıt
  tek kalıyor; altıncı alan eklendiğinde tek kalan kayıt 1.242'ye, yani 0,9857'ye çıkıyor.
- Kimliksizleştirme bir sütunu siler, birleştirilebilirliği silmez; belirleyici olan alanların
  sayısı ve çözünürlüğüdür.
- Tek bir eğitim kaydının çıkarılması doğrusal modelin çıktısını en çok 0,0313 oynatıyor ve iki
  tahmini değiştiriyor; ortanca iz 0,0030.
- Aynı ölçüm hücre modelinde 0,7778 veriyor ve 14 tahmini değiştiriyor, çünkü 66 hücrenin 13'ünde
  tek bir kayıt var: bir çıktı ne kadar az kayda dayanıyorsa o kayıtlar o çıktıda o kadar
  açıktadır.
- Gürültünün bedeli modele göre değişiyor: doğrusal modelde izi örtmek 0,04 gürültü ve 0,0022
  doğruluk isterken, hücre modelinde 0,80 gürültü ve taban çizgisinin 0,1669 altına düşmek
  istiyor.

## Sonraki Adım

Üç derste zarar üç ayrı biçimde ölçüldü ve üçünde de azaltılacak bir kalem bulundu: yanlılığın
kaynağı ayrıldı, adalet ölçütü seçildi ve seçimin bedeli sayıldı, kayıt izi ölçülüp gürültüyle
örtüldü. Ölçülenlerin hiçbiri şu ana kadar modeli **kullanacak kişiye** ulaşmıyor. Bu dersteki üç
tabloyu görmemiş biri, modeli devraldığında hangi alt gruplarda ölçülmediğini, hangi eşikle hangi
adalet ölçütünün seçildiğini ve çıktıya gürültü eklenip eklenmediğini nereden bilecek. Sonraki
ders bu soruyu bir sayıya çevirir: modeli devralan kişinin sorabileceği soru kümesinden kaçı
yazılı bir beyanla kapanıyor ve hangileri cevapsız kalıyor.
