Ders 13 / 15
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.
İçindekiler
İ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.
# 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.
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.
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.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.