İçeriğe geç
academia.sh

Ders 11 / 23

İlgililik Puanlaması

Puanlayıcı üç bileşenden kurulur — terim sıklığı, ters belge sıklığı ve alan uzunluğu — ve bir belgenin sırasının hangi bileşenden geldiği tek tek gösterilir; kesinlik ile anma burada tanımlanır ve sıralamanın kesinliği 0,353'ten 0,640'a çıkardığı, ama modelin göremediği bir ölçütte tavana vurduğu ölçülür.

İçindekiler

Önceki derste puan hep yer tutucu bir formülle hesaplandı: önce karşılanan koşul sayısı, sonra terim sıklığının alan uzunluğuna bölümü. İkisi de sıralama üretti, ama ikisi de sorunun yarısını atladı. Bir terimin bir belgede geçmesi, o terimin derlemde ne kadar seyrek olduğu bilinmeden anlam taşımaz: “ve” sözcüğü katalogdaki 6.000 özetin hepsinde geçer ve hiçbir şeyi ayırt etmez, “gökbilim” iki yüz kadar özette geçer ve tek başına belgeyi neredeyse belirler.

İlgililik puanı (relevance score) üç bileşenden kurulur. Terim sıklığı (term frequency) terimin belgede kaç kez geçtiğidir ve doyuma ulaşır — beşinci geçiş birinciden daha az şey söyler. Ters belge sıklığı (inverse document frequency) terimin derlemdeki seyrekliğidir; seyrek terim çok, yaygın terim az ağırlık taşır. Alan uzunluğu düzeltmesi ise üç sözcüklük bir kitap adındaki eşleşmeyle on dört sözcüklük bir özetteki eşleşmeyi ayırır. Bu ders puanlayıcıyı kurar, bir belgenin sırasının hangi bileşenden geldiğini gösterir ve sonucun ne kadarının doğru olduğunu ölçmek için iki ölçü tanımlar.

Derlem, Model ve Gereksinim

Derlem önceki derslerin modülüdür: 6.000 kitap kaydı, tohum 271828, belirlenimli üretim. SI8 (varsayım): puanlanan alanlar ad ve ozet; alan ağırlığı yoktur, ikisi de bire bir toplanır. Terim sıklığı doyum katsayısı 1,2, alan uzunluğu düzeltme katsayısı 0,75’tir; ters belge sıklığı, derlem boyutuyla belge sıklığının oranından logaritmayla bulunur. SI9 (varsayım): okurun gereksinimi sorgudan geniştir — “çocuk ve öykü etiketli, türkçe bir kitap” arıyordur, ama arama kutusuna yalnız “çocuk öykü” yazar. etiket, dil ve yil alanları bu derste dizinlenmez; puanlayıcı gereksinimin dil ölçütünü göremez. Bu, gerçek bir katalogda olağan durumdur.

// derlem.mjs — kutuphane katalogu derlemi ve konum bilgili ters dizin.
// Tohum 271828, 6000 belge; konudaki butun olcumler bu modulu paylasir.
export const TOHUM = 271828, N = 6000;
let c = TOHUM;                                       // gorunur tohum, belirlenimli uretec
const r = () => { c = (c + 0x6d2b79f5) | 0; let t = Math.imul(c ^ (c >>> 15), 1 | c);
  t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t; return ((t ^ (t >>> 14)) >>> 0) / 4294967296; };
const sec = (d, e = 1) => d[Math.floor(r() ** e * d.length)];   // e>1: bas ogeler sik, son ogeler seyrek

const SIFAT = ["eleştirel", "kısa", "resimli", "seçme", "karşılaştırmalı"];
const TUR = ["deneme", "öykü", "roman", "inceleme", "antoloji"];
const ALAN = ["çocuk", "tarih", "bilim", "felsefe", "toplum"];
const SON = ["seçkisi", "kitabı", "derlemesi", "dizisi"];
const NIT = ["kapsamlı", "özlü", "tanıtıcı", "tartışmalı"];
const KONU = ["eğitim", "göç", "kent", "bellek", "doğa", "müzik", "hukuk", "kimlik", "emek", "aile",
  "savaş", "gelenek", "sağlık", "yolculuk", "mimarlık", "arkeoloji", "denizcilik", "gökbilim"];
const YAZAR = ["Ahmet Yıldız", "Zeynep Kaya", "Kemal Demir", "Elif Şahin", "Necati Aydın"];
const DIL = ["türkçe", "ingilizce", "almanca"];

export const KATALOG = [];
for (let i = 1; i <= N; i += 1) {
  const s = sec(SIFAT, 1.5), t = sec(TUR, 1.5), a = sec(ALAN, 2), k = r();
  const desen = k < 0.18 ? `${s} ${t}` : k < 0.30 ? `${s} bir ${t}`
    : k < 0.40 ? `${s} ve kuramsal ${t}` : k < 0.50 ? `${t} ve ${s} inceleme`
    : k < 0.70 ? `${s} bir anlatı` : k < 0.88 ? `çağdaş bir ${t}` : "alan yazını taraması";
  KATALOG.push({ id: `K-${String(i).padStart(4, "0")}`, ad: `${a} ${t} ${sec(SON)}`,
    ozet: `${a} alanında ${desen}; ${sec(KONU, 3)} ve ${sec(KONU, 3)} üzerine ` +
      `${sec(NIT)} bir ${sec(TUR, 1.5)} olarak okunabilir.`,
    etiket: [a, t], yazar: sec(YAZAR), yil: 1990 + Math.floor(r() * 35), dil: sec(DIL, 2) });
}

export const belirtecle = (m) => m.toLocaleLowerCase("tr").split(/[^\p{L}\p{N}]+/u).filter(Boolean);

// Ters dizin: "alan|terim" -> Map(belge sirasi -> konumlar); uzunluk: alan basina belirtec sayisi.
export function tersDizin(alanlar) {
  const g = new Map(), uzunluk = new Map();
  KATALOG.forEach((b, i) => {
    for (const alan of alanlar) {
      const tk = belirtecle(String(b[alan]));
      uzunluk.set(`${alan}|${i}`, tk.length);
      tk.forEach((t, p) => {
        let l = g.get(`${alan}|${t}`); if (!l) g.set(`${alan}|${t}`, (l = new Map()));
        let k2 = l.get(i); if (!k2) l.set(i, (k2 = [])); k2.push(p);
      });
    }
  });
  return { g, uzunluk };
}

Puanlayıcı

// puan.mjs — ilgililik puanlayicisi. Ayni dizinde derlem.mjs bulunur.
// Puan uc bilesenden gelir: terim sikligi (doyuma ulasan), ters belge sikligi, alan uzunlugu.
import { KATALOG, TOHUM, tersDizin } from "./derlem.mjs";
const { g, uzunluk } = tersDizin(["ad", "ozet"]);          // etiket, dil ve yil dizinlenmez
const N = KATALOG.length, ALANLAR = ["ad", "ozet"], K = 1.2, B = 0.75;
const liste = (alan, terim) => g.get(`${alan}|${terim}`) ?? new Map();
const ortUzunluk = Object.fromEntries(ALANLAR.map((a) => {
  let t = 0; for (let d = 0; d < N; d += 1) t += uzunluk.get(`${a}|${d}`); return [a, t / N];
}));
const idf = (alan, terim) => { const df = liste(alan, terim).size; return Math.log(1 + (N - df + 0.5) / (df + 0.5)); };

function bilesen(alan, terim, d, kip) {
  const tf = (liste(alan, terim).get(d) ?? []).length;
  if (tf === 0) return 0;
  if (kip === "yalniz terim sikligi") return tf;
  if (kip === "terim x ters belge sikligi") return tf * idf(alan, terim);
  const uz = uzunluk.get(`${alan}|${d}`) / ortUzunluk[alan];      // alan uzunlugu duzeltmesi
  return idf(alan, terim) * (tf * (K + 1)) / (tf + K * (1 - B + B * uz));
}
const puanla = (d, kip) => TERIM.reduce((p, t) => p + ALANLAR.reduce((q, a) => q + bilesen(a, t, d, kip), 0), 0);
const TERIM = ["çocuk", "öykü"], KIPLER = ["yalniz terim sikligi", "terim x ters belge sikligi", "tam model"];

const aday = [...Array(N).keys()].filter((d) => TERIM.every((t) => ALANLAR.some((a) => liste(a, t).has(d))));
const ilgili = new Set(aday.filter((d) => KATALOG[d].etiket.includes("çocuk")
  && KATALOG[d].etiket.includes("öykü") && KATALOG[d].dil === "türkçe"));
console.log(`derlem ${N} belge, tohum ${TOHUM};  soru "çocuk öykü"`);
console.log(`aday kume ${aday.length} belge;  gereksinim: çocuk+öykü etiketli ve türkçe kitap -> ${ilgili.size} belge ilgili`);
for (const t of TERIM) for (const a of ALANLAR)
  console.log(`  ${a}|${t}`.padEnd(13) + `belge sikligi ${String(liste(a, t).size).padStart(4)}   ` +
    `ters belge sikligi ${idf(a, t).toFixed(3)}   ortalama alan uzunlugu ${ortUzunluk[a].toFixed(2)}`);

const sirali = (kip) => [...aday].sort((x, y) => puanla(y, kip) - puanla(x, kip) || x - y);
const tam = sirali("tam model");
console.log("puanin bilesenleri: birinci ve besyuzuncu basamak");
for (const d of [tam[0], tam[499]]) {
  const par = [];
  for (const t of TERIM) for (const a of ALANLAR) {
    const k = bilesen(a, t, d, "tam model");
    if (k > 0) par.push(`${a}|${t} ${k.toFixed(2)} (siklik ${(liste(a, t).get(d) ?? []).length}, uzunluk ${uzunluk.get(`${a}|${d}`)})`);
  }
  console.log(`  ${String(tam.indexOf(d) + 1).padStart(3)}. ${KATALOG[d].id} puan ${puanla(d, "tam model").toFixed(2)} = ${par.join(" + ")}`);
}

const kesinlik = (l, k) => l.slice(0, k).filter((d) => ilgili.has(d)).length / Math.min(k, l.length);
const anma = (l, k) => l.slice(0, k).filter((d) => ilgili.has(d)).length / ilgili.size;
console.log("siralama modeli".padEnd(28) + "farkli puan  ilk on ortak  en buyuk oynama  kesinlik@10  kesinlik@50");
for (const kip of KIPLER) {
  const l = sirali(kip);
  const deger = new Set(aday.map((d) => puanla(d, kip).toFixed(6))).size;
  const ortak = l.slice(0, 10).filter((d) => tam.slice(0, 10).includes(d)).length;
  const oynama = Math.max(...aday.map((d) => Math.abs(l.indexOf(d) - tam.indexOf(d))));
  console.log(kip.padEnd(28) + String(deger).padStart(11) + String(ortak).padStart(14) +
    String(oynama).padStart(17) + kesinlik(l, 10).toFixed(3).padStart(13) + kesinlik(l, 50).toFixed(3).padStart(13));
}
console.log(`siralamasiz kume: kesinlik ${(ilgili.size / aday.length).toFixed(3)}, anma 1.000`);
for (const k of [10, 50, 200, 567, 984])
  console.log(`  ilk ${String(k).padStart(3)} sonuc: kesinlik ${kesinlik(tam, k).toFixed(3)}  anma ${anma(tam, k).toFixed(3)}`);
const yanlis = tam.slice(0, 50).filter((d) => !ilgili.has(d));
console.log(`ilk 50 sonuctaki ${yanlis.length} yanlis belgenin ilki ${KATALOG[yanlis[0]].id}: ` +
  `${KATALOG[yanlis[0]].ad}, dil ${KATALOG[yanlis[0]].dil}, etiket ${KATALOG[yanlis[0]].etiket.join("+")}`);
derlem 6000 belge, tohum 271828;  soru "çocuk öykü"
aday kume 984 belge;  gereksinim: çocuk+öykü etiketli ve türkçe kitap -> 347 belge ilgili
  ad|çocuk   belge sikligi 2678   ters belge sikligi 0.807   ortalama alan uzunlugu 3.00
  ozet|çocuk belge sikligi 2678   ters belge sikligi 0.807   ortalama alan uzunlugu 14.02
  ad|öykü    belge sikligi 1271   ters belge sikligi 1.552   ortalama alan uzunlugu 3.00
  ozet|öykü  belge sikligi 1869   ters belge sikligi 1.166   ortalama alan uzunlugu 14.02
puanin bilesenleri: birinci ve besyuzuncu basamak
    1. K-0078 puan 4.83 = ad|çocuk 0.81 (siklik 1, uzunluk 3) + ozet|çocuk 0.83 (siklik 1, uzunluk 13) + ad|öykü 1.55 (siklik 1, uzunluk 3) + ozet|öykü 1.64 (siklik 2, uzunluk 13)
  500. K-3736 puan 3.17 = ad|çocuk 0.81 (siklik 1, uzunluk 3) + ozet|çocuk 0.81 (siklik 1, uzunluk 14) + ad|öykü 1.55 (siklik 1, uzunluk 3)
siralama modeli             farkli puan  ilk on ortak  en buyuk oynama  kesinlik@10  kesinlik@50
yalniz terim sikligi                  3             3              468        0.700        0.640
terim x ters belge sikligi            4             3              342        0.700        0.640
tam model                            10            10                0        0.600        0.640
siralamasiz kume: kesinlik 0.353, anma 1.000
  ilk  10 sonuc: kesinlik 0.600  anma 0.017
  ilk  50 sonuc: kesinlik 0.640  anma 0.092
  ilk 200 sonuc: kesinlik 0.615  anma 0.354
  ilk 567 sonuc: kesinlik 0.612  anma 1.000
  ilk 984 sonuc: kesinlik 0.353  anma 1.000
ilk 50 sonuctaki 18 yanlis belgenin ilki K-0171: çocuk öykü seçkisi, dil almanca, etiket çocuk+öykü

Bir Sıra Nereden Geliyor

İlk tablo bileşenlerin kaynağını verir. “Çocuk” 2.678 belgede geçer ve ters belge sıklığı 0,807’dir; “öykü” kitap adlarında 1.271 belgede geçer ve 1,552 taşır. Aynı terim özette 1.869 belgede geçtiği için orada yalnız 1,166 eder — aynı sözcüğün ağırlığı alandan alana değişir, çünkü seyreklik alan içinde ölçülür.

Birinci basamaktaki K-0078’in puanı 4,83’tür ve dördü de sıfırdan büyük dört bileşenin toplamıdır. Bu puanın 3,19’u, yani %66’sı “öykü” teriminden gelir; “çocuk” terimi 1,64 katkı yapar. Sıralamayı belirleyen şey, sorgunun seyrek terimidir. Beş yüzüncü basamaktaki K-3736 aynı üç bileşene sahiptir ve tek farkı dördüncü bileşenin bulunmamasıdır: özetinde “öykü” hiç geçmez. Bir bileşenin yokluğu 1,66 puan ve 499 basamak eder. Katalogda bu iki kitabın ikisi de çocuk öykü kitabıdır; aralarındaki tek fark, birinin özetinin türü iki kez anmasıdır.

Alan uzunluğunun payı daha küçük ama görünürdür. K-0078’in özeti 13 belirteçtir, K-3736’nınki 14; ortalama 14,02’dir. Bu bir belirteçlik fark ozet|çocuk bileşenini 0,83’ten 0,81’e indirir. Kitap adı alanında ortalama uzunluk tam 3,00 olduğu için düzeltme etkisizdir — her adın üç sözcük olduğu bir derlemde alan uzunluğu ayırt edici değildir. Düzeltme, uzunluğu değişen alanlarda çalışır.

Üç Model, Üç Sıra

Model tablosu bileşenlerin sıraya ne yaptığını ölçer. Yalnız terim sıklığı kullanıldığında 984 aday belge yalnız 3 ayrı puan değeri alır: liste üç yığına ayrılır ve yığın içindeki sıra belge numarasına kalır. Ters belge sıklığı eklendiğinde değer sayısı 4’e, alan uzunluğu düzeltmesi de eklendiğinde 10’a çıkar. Çözünürlük arttıkça beraberlikler çözülür. Tam modele göre en büyük basamak oynaması, yalnız terim sıklığı modelinde 468, ara modelde 342 basamaktır — 984 belgelik bir listede bu, bir belgenin ortasından başına gitmesidir.

İlk on sonuçta üç modelin ortak belgesi yalnız 3 tanedir. Kesinlik değerlerine bakıldığında tam model ilk onda 0,600 ile öteki iki modelin 0,700’ünün altında kalır. Bu, tam modelin kötü olduğunu göstermez: ilk elli sonuçta üç model de 0,640 verir ve fark, aşağıda görüleceği gibi modelin hiç göremediği bir ölçütten doğan gürültüdür. On sonuçluk bir örneklem üzerinden model seçmek, ölçünün kendisini yanlış kullanmaktır.

Kesinlik ve Anma

İki ölçü sonucun ne kadar doğru olduğunu ayrı yönlerden sorar. Kesinlik (precision) dönen sonuçların ne kadarının ilgili olduğudur: yanlış getirilen belgeyi cezalandırır. Anma (recall) ilgili belgelerin ne kadarının döndüğüdür: kaçırılan belgeyi cezalandırır. Aynı ikili yazılım testinde başka adlarla anılır — İşlevsel Olmayan Test kursundaki statik güvenlik taraması dersinde bir bulgunun yanlış getirilmesi yanlış alarm, gerçek bir açığın hiç bildirilmemesi kaçırma olarak geçer; kesinlik yanlış alarmın, anma kaçırmanın ölçüsüdür.

Sıralamasız küme 984 belgedir ve içinde 347 ilgili belge vardır: kesinlik 0,353, anma 1,000. Boole sorgusunun tipik dengesi budur — hiçbir ilgili belge kaçmaz, ama üçte ikisi gereksizdir. Sıralama bu dengeyi kesme noktasına bağlar. İlk 50 sonuçta kesinlik 0,640’a çıkar, anma 0,092’ye düşer. İlk 200’de kesinlik 0,615, anma 0,354’tür. İlk 567’de anma 1,000’e ulaşır: 347 ilgili belgenin tamamı listenin ilk %58’indedir, yani puanlayıcı hiç ilgili belgeyi listenin dibine atmamıştır.

Kesinliğin 0,64 dolayında takılması dersin son bulgusudur. İlk 50 sonuçtaki 18 yanlış belgenin ilki K-0171’dir ve adı “çocuk öykü seçkisi”dir — okurun aradığı türden bir kitaptır, yalnız almancadır. Puanlayıcı bu belgeyi haklı olarak üste koymuştur, çünkü metinsel olarak kusursuz eşleşmedir; gereksinimi karşılamayan yanı puanlayıcının hiç görmediği bir alandadır. Buradan çıkan kural şudur: bir ölçüt puanlayıcının göremediği bir alandaysa, hiçbir ağırlık ayarı kesinliği artırmaz. Doğru araç önceki dersin süzgecidir; puan ayarı yalnız modelin gördüğü alanlarda iş görür.

Özet

  • İlgililik puanı üç bileşenden gelir: doyuma ulaşan terim sıklığı, ters belge sıklığı ve alan uzunluğu düzeltmesi; aynı terim kitap adında 1,552, özette 1,166 ağırlık taşır.
  • Birinci basamaktaki belgenin 4,83 puanının %66’sı sorgunun seyrek teriminden gelir; bir bileşenin yokluğu 1,66 puan ve 499 basamak eder.
  • Bileşen eklendikçe puanın çözünürlüğü artar: 984 aday belge 3, 4 ve 10 ayrı puan değeri alır; en büyük basamak oynaması 468’dir.
  • Kesinlik dönen sonuçların ne kadarının ilgili olduğu, anma ilgili belgelerin ne kadarının döndüğüdür; sıralamasız kümede kesinlik 0,353 ve anma 1,000’dir.
  • Sıralama kesinliği ilk 50 sonuçta 0,640’a çıkarır ve ilk 567 sonuçta anmayı 1,000’e taşır; ama gereksinimin dil ölçütü dizinlenmediği için kesinlik 0,64 dolayında tavana vurur.

Sonraki Adım

Puanlayıcı çalışıyor ve ürettiği sıranın hangi bileşenden geldiği artık görülebiliyor. Bu, sıranın istenen sıra olduğu anlamına gelmez. Kütüphane için kitap adındaki eşleşme özetteki eşleşmeden daha güçlü bir işarettir, oysa şu anki modelde ikisi bire bir toplanıyor. Yeni basımların eski basımlara göre öne çıkması istenebilir, ama yayın yılı puana hiç girmiyor. Ödünç alınma sayısı gibi metinle ilgisi olmayan bir büyüklük de sıraya karışabilir. Bunların hepsi puanın bileşenlerine dışarıdan yapılan müdahalelerdir ve her biri kümeyi değiştirmeden sırayı değiştirir — tıpkı isteğe bağlı koşulun yaptığı gibi, ama bu kez ölçülü bir katsayıyla. Sonraki ders bu ayarları kurar ve her ayarın ilk on sonuçta kaç belgeyi yer değiştirdiğini, kesinliği kaç puan oynattığını 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