---
title: 'Karma Arama'
source: 'https://academia.sh/tr/kurslar/rag/karma-arama'
course: 'Gömme Vektörleri ve Erişim Artırılmış Üretim'
language: tr
updated: '2026-08-17T18:06:35+00:00'
license: 'CC BY-SA 4.0'
---

# Karma Arama

Anahtar sözcük eşleşmesi ile gömme aramasının ayrı ayrı ve birlikte ölçülmesi. Üç kurgu sorgu sınıfında üç kurulum yan yana koşuluyor: abone dilinde anahtar sözcük 0,0500, gömme 0,5000; belge dilinde ikisi de 0,5000; belge kodu sorgusunda anahtar sözcük 1,0000, gömme 0,0000. Sıra temelli birleştirme belge dili sınıfında 0,4000 veriyor, yani ikisinden de kötü; bu sabit 5, 20 ve 60'ta sürüyor. Kod sınıfında birleştirme hedef belgeyi ilk beşte tutma payını 1,0000'den 0,0500'e düşürüyor. Nedeni iki listenin ilk beşinin ortak belge sayısıdır: abone dilinde 0,20, belge dilinde 1,05. İki listede de ikinci sırada duran bir belge, birinde birinci öbüründe yok olan belgeyi geçiyor. Birleştirme yirminci sıraya kadar anmayı 0,7122'den 0,7209'a çıkarıyor; kazandığı yer derinlik, kaybettiği yer ilk sıradır.

Önceki derste sorgu ile belge arasındaki bağ tek bir yerden kuruldu: gömme vektörlerinin açısı.
Süzgeç bu bağı daralttı, değiştirmedi. Oysa bir destek dağarcığında aranan şey her zaman bir anlam
değildir. Bir belge kodu, bir hata numarası ya da bir yordamın tam adı arandığında sorulan soru
"buna benzer ne var" değil, "bu tam olarak nerede geçiyor" sorusudur. Anlam benzerliği bu sorunun
yanından geçer.

**Karma arama** iki sıralamayı aynı sorgu için birlikte çalıştırıp sonuçlarını tek listede
toplamaktır. Beklenti toplamın parçalarından iyi olmasıdır: gömmenin göremediği tam eşleşmeyi
anahtar sözcük, anahtar sözcüğün göremediği eş anlamı gömme yakalasın. Bu ders üç kurulumu
(yalnız anahtar sözcük, yalnız gömme, birleşik) üç sorgu sınıfında yan yana ölçer. Sonuçlardan
biri beklentiyi karşılamaz: bir sorgu sınıfında birleşik, **iki yordamdan da** kötü kalır.

- **GM48.** Dağarcık, gömme yordamı, belirteçleyici ve sorgu sınıfları **kurgudur**; gerçek bir
  arama motoru, vektör deposu ya da gömme uç noktası çağrılmaz. Tohum **20260218**.
- **GM49.** Belgenin **arama metni** kodu ile birlikte tutulur. Kod bir kavram yüzeyi olmadığı
  için gömme vektörünü değiştirmez; blokta gösterilir.
- **GM50. Üç sorgu sınıfı** aynı belgelerden türetilir ve yalnız yüzeyleri ayrılır: **abone dili**
  sorgu yüzeyini, **belge dili** belge yüzeyini, **kod sorgusu** belge kodunu taşır. Üçü de kırk
  sorgudur.
- **GM51. Anahtar sözcük sıralaması** örtüşen belirteç sayısıdır. İlgililik puanlaması
  Veritabanları müfredatının Arama Motorları ve Metin Erişimi kursunda kuruldu ve ölçüldü; burada
  tekrarlanmaz. Bu derste anahtar sözcük tarafının tek işlevi **ikinci bir sıralama** üretmektir.
- **GM52. Birleştirme sıra temellidir**: bir belgenin puanı iki listedeki sırasının tersleri
  toplamıdır, `1 / (sabit + sıra)`. Sabit varsayılan olarak 20'dir ve 5 ile 60'ta da sınanır.
- **GM53. İlk sıra isabeti** ilk sonucun hedef kavramı taşıma payı, **erişim kesinliği** ilk beş
  sonucun aynı payı, **erişim anması** hedef kavramı taşıyan belgelerin ilk yirmide yakalanma
  payıdır. **Hedef belge** sütunu sorgunun türetildiği belgenin ilk beşte olma payıdır.
- **GM54.** Her kavramı birden çok belge taşır; bu yüzden kesinlik ve anma farklı derinliklerde
  okunur ve tek sayıya indirilmez.
- **GM55.** Üç sıralama da **belirlenmiştir**: aynı sorgu iki koşumda aynı listeyi verir. Bu dersin
  koşumdan bağımsız ölçüsü **iki listenin ilk beşindeki ortak belge sayısıdır** ve sorgudan
  bağımsız olarak yordam çiftinin bir özelliğidir.
- **GM56.** Hiçbir kavram yüzeyi taşımayan bir sorgu **sıfır vektör** üretir; bütün benzerlikler
  sıfır olur ve sıra saklama sırasına düşer. Bu bir kusur değil, gömmenin tanım alanının dışına
  çıkmasıdır ve kod sınıfında ölçülür.
- **GM57.** Bu ders konunun kapanışıdır; getirilen parçanın modele ne yaptığı ölçülmez, sonraki
  konuya bırakılır.

## Üç Sorgu Sınıfı

```python
# KURGU dagarcik, KURGU gomme benzeticisi, KURGU sorgu siniflari. Gercek uc nokta yok.
TOHUM, M32 = 20260218, 0xFFFFFFFF
BOYUT = 32


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


def belirtecle(m):               # KURGU belirtecleyici, parca en cok bes damga
    b = []
    for s in m.lower().replace(",", " , ").split():
        while len(s) > 5:
            b.append(s[:5])
            s = s[5:]
        b.append(s)
    return b


# ---- KURGU anlam ekseni: her kavramin belge dilinde ve sorgu dilinde ayri yuzeyi var
SINIF = ["tarife", "ariza", "sayac", "kesinti", "bakim"]
KOD = {"tarife": "TR", "ariza": "AR", "sayac": "SY", "kesinti": "KS", "bakim": "BK"}
KAVRAM = {                       # kavram: (sinif, belge yuzeyi, sorgu yuzeyi)
    "basamak":   ("tarife", "kademe esigi", "hangi dilimdeyim"),
    "birim":     ("tarife", "birim ucret", "metrekup fiyati"),
    "abonetip":  ("tarife", "abone tipi", "mesken mi isyeri mi"),
    "gecis":     ("tarife", "tarife gecisi", "plan degistirme"),
    "arizakod":  ("ariza", "ariza kodu", "hata numarasi"),
    "sizinti":   ("ariza", "hat sizintisi", "su kacagi"),
    "basinc":    ("ariza", "basinc dususu", "zayif akis"),
    "ekip":      ("ariza", "saha ekibi", "gorevli ne zaman gelir"),
    "endeks":    ("sayac", "endeks degeri", "sayac ustundeki rakam"),
    "okuma":     ("sayac", "okuma yordami", "nasil kaydediliyor"),
    "degisim":   ("sayac", "sayac degisimi", "cihaz yenileme"),
    "dogrula":   ("sayac", "okuma dogrulamasi", "yanlis girilmis mi"),
    "planli":    ("kesinti", "planli kesinti", "onceden duyurulan durma"),
    "duyuru":    ("kesinti", "duyuru kanali", "nereden ogrenirim"),
    "sure":      ("kesinti", "kesinti suresi", "ne kadar surer"),
    "geridonus": ("kesinti", "yeniden verme", "ne zaman gelir"),
    "periyot":   ("bakim", "periyodik bakim", "duzenli kontrol"),
    "vana":      ("bakim", "vana kontrolu", "musluk kapatma duzeni"),
    "filtre":    ("bakim", "filtre degisimi", "temizleme parcasi"),
    "kalib":     ("bakim", "kalibrasyon kaydi", "olcum ayari"),
}
ANAHTAR = list(KAVRAM)
ORTAK = ["kayit", "bolge", "donem", "islem", "form", "onay", "not"]

BELGE = []
for i in range(200):
    r = uretec(TOHUM + 7919 * i)
    s = SINIF[ayrik(r(), [0.22, 0.24, 0.20, 0.18, 0.16])]
    kav = [k for k in ANAHTAR if KAVRAM[k][0] == s]
    ana = kav[int(r() * len(kav))]
    n = 2 + int(r() * 4)
    par, kavlar = [], [ana]
    for _ in range(n):
        y = kav[int(r() * len(kav))]
        kavlar.append(y)
        o = ORTAK[int(r() * len(ORTAK))]
        par.append(f"{KAVRAM[y][1]} icin {o} tutulur ve {KAVRAM[ana][1]} ile birlikte yazilir")
    BELGE.append({"kod": f"{KOD[s]}{i + 1:03d}", "sinif": s, "ana": ana, "kavram": kavlar,
                  "baslik": f"{KAVRAM[ana][1]} yordami", "par": par})


def metin(d):
    return d["baslik"] + " " + " ".join(d["par"])


def _kavramla(m):                # yuzey once kavrama cevrilir
    v = [0.0] * len(ANAHTAR)
    dm = " " + m.lower() + " "
    for i, k in enumerate(ANAHTAR):
        if KAVRAM[k][1] in dm:
            v[i] += 1.0
        if KAVRAM[k][2] in dm:
            v[i] += 1.0
    return v


IZDUS = []
for i in range(len(ANAHTAR)):
    r = uretec(TOHUM ^ (i + 1) * 2654435761)
    IZDUS.append([r() * 2 - 1 for _ in range(64)])


def gom(m, boyut=BOYUT):         # kavram sonra boyuta dusurulur
    v = [0.0] * boyut
    for i, a in enumerate(_kavramla(m)):
        if a:
            for j in range(boyut):
                v[j] += a * IZDUS[i][j % 64]
    n = sum(x * x for x in v) ** 0.5
    return [x / n for x in v] if n else v


def aci(a, b):
    return sum(x * y for x, y in zip(a, b))


K, SABIT = 5, 20
ARAMA = [d["kod"] + " " + metin(d) for d in BELGE]   # kod belgenin arama metnine girer
VEK = [gom(a) for a in ARAMA]
BEL = [set(belirtecle(a)) for a in ARAMA]


def sorgular(kip):               # ayni belgelerden uc ayri yuzey
    q = []
    for i in range(40):
        r = uretec(TOHUM + 104729 * i)
        d = BELGE[int(r() * len(BELGE))]
        o = ORTAK[int(r() * len(ORTAK))]
        q.append({"metin": {"abone": f"{KAVRAM[d['ana']][2]} {o}",
                            "belge": f"{KAVRAM[d['ana']][1]} {o}",
                            "kod": f"{d['kod']} numarali belge"}[kip],
                  "kavram": d["ana"], "kod": d["kod"]})
    return q


SINIFLAR = {k: sorgular(k) for k in ("abone", "belge", "kod")}


def anahtar_sira(m):             # ortusen belirtec sayisina gore
    qb = set(belirtecle(m))
    return sorted(range(len(BELGE)), key=lambda i: -len(qb & BEL[i]))


def gomme_sira(m):
    qv = gom(m)
    return sorted(range(len(BELGE)), key=lambda i: -aci(qv, VEK[i]))


def birlesik_sira(m, sabit=SABIT):   # sira temelli birlestirme
    pa = {i: 1.0 / (sabit + n) for n, i in enumerate(anahtar_sira(m))}
    pg = {i: 1.0 / (sabit + n) for n, i in enumerate(gomme_sira(m))}
    return sorted(range(len(BELGE)), key=lambda i: -(pa[i] + pg[i]))


for k, s in SINIFLAR.items():
    print(f"{k:6s} ornek sorgu: {s[0]['metin']}")
print(f"belge kodu gommeyi degistirmiyor: "
      f"{gom(ARAMA[0]) == gom(metin(BELGE[0]))} , kod sorgusunun vektor uzunlugu "
      f"{sum(x * x for x in gom(SINIFLAR['kod'][0]['metin'])):.1f}")
```

```
abone  ornek sorgu: nasil kaydediliyor form
belge  ornek sorgu: okuma yordami form
kod    ornek sorgu: SY194 numarali belge
belge kodu gommeyi degistirmiyor: True , kod sorgusunun vektor uzunlugu 0.0
```

Üç sorgu aynı belgeden türedi ve aynı şeyi soruyor; ayrıldıkları yer yalnız yüzey. Son satır iki
şeyi ölçüyor. Belge kodunun arama metnine eklenmesi gömme vektörünü **değiştirmiyor**: kod bir
kavram yüzeyi değil, dolayısıyla gömme onu görmüyor. İkincisi daha sert: kod sorgusunun vektör
uzunluğu **0,0**. Sorguda tanınan hiçbir kavram olmadığı için vektör sıfırdır, bütün açı
benzerlikleri sıfır çıkar ve sıralama saklama sırasına düşer. Gömme bu sorguda yanılmıyor,
**tanım alanının dışında** kalıyor.

## Üç Kurulumun Tablosu

```python
def olc(S, sirala):
    ilk = kes = an = hed = 0.0
    for q in S:
        ilgili = {i for i, d in enumerate(BELGE) if d["ana"] == q["kavram"]}
        s = sirala(q["metin"])
        ilk += s[0] in ilgili
        kes += len(set(s[:K]) & ilgili) / K
        an += len(set(s[:20]) & ilgili) / len(ilgili)
        hed += any(BELGE[i]["kod"] == q["kod"] for i in s[:K])
    return [x / len(S) for x in (ilk, kes, an, hed)]


YORDAM = (("anahtar", anahtar_sira), ("gomme", gomme_sira), ("birlesik", birlesik_sira))
print("sinif  yordam     ilk1  kesinlik@5  anma@20  hedef belge@5")
for kip, S in SINIFLAR.items():
    for ad, f in YORDAM:
        d = olc(S, f)
        print(f"{kip:6s} {ad:8s} {d[0]:>6.4f} {d[1]:>11.4f} {d[2]:>8.4f} {d[3]:>15.4f}")
print("belge dili sinifinda birlesigin ilk1 degeri , sabit 5 / 20 / 60: "
      + " / ".join(f"{olc(SINIFLAR['belge'], lambda m, c=c: birlesik_sira(m, c))[0]:.4f}"
                   for c in (5, 20, 60)))
```

```
sinif  yordam     ilk1  kesinlik@5  anma@20  hedef belge@5
abone  anahtar  0.0500      0.1200   0.1183          0.0500
abone  gomme    0.5000      0.4600   0.7014          0.1500
abone  birlesik 0.4500      0.2800   0.4472          0.1250
belge  anahtar  0.5000      0.3650   0.6722          0.1750
belge  gomme    0.5000      0.4700   0.7122          0.1500
belge  birlesik 0.4000      0.4250   0.7209          0.1250
kod    anahtar  1.0000      0.2500   0.1950          1.0000
kod    gomme    0.0000      0.0800   0.1078          0.0250
kod    birlesik 0.0000      0.0850   0.1950          0.0500
belge dili sinifinda birlesigin ilk1 degeri , sabit 5 / 20 / 60: 0.4500 / 0.4000 / 0.4000
```

İlk iki üçlü karma aramanın gerekçesini kuruyor. Abone dilinde anahtar sözcük 0,0500, gömme
0,5000; kod sorgusunda anahtar sözcük **1,0000**, gömme **0,0000**. İki yordam aynı dağarcıkta
birbirinin tam tersi yerlerde çalışıyor, ve tek bir yordam seçmek sorgu sınıflarından birini
tamamen feda etmek demek.

Birleşik satırlar bu feragatin ortadan kalkmadığını gösteriyor. Abone dilinde birleşik 0,4500 ile
gömmenin biraz altında; beklenen bedel budur. Belge dilinde ise iki yordam da 0,5000 verirken
birleşik **0,4000**. Toplam, iki parçasının **ikisinden de** kötü. Son satır bunun bir sabit
seçiminin oyunu olmadığını söylüyor: 5, 20 ve 60'ta 0,4500 / 0,4000 / 0,4000, üçü de 0,5000'in
altında.

Kod sınıfı en pahalı satırdır. Anahtar sözcük hedef belgeyi kırk sorgunun kırkında ilk beşe
sokuyor; birleşik bunu **0,0500**'e düşürüyor. Karma aramanın var olma gerekçesi olan sorgu
sınıfında, birleştirme çalışan yordamı çalışmayanla birlikte batırıyor. Sebep tablonun kendi
içinde: gömme tarafı bu sınıfta sıfır vektörle çalışıyor ve ürettiği sıra bilgi taşımıyor, ama
birleştirme bunu bilmiyor ve o sıraya **eşit ağırlık** veriyor.

Bir sütun ters yöne bakıyor. Belge dilinde anma@20 anahtar sözcükte 0,6722, gömmede 0,7122,
birleşikte **0,7209**. Yirminci sıraya kadar birleştirme gerçekten kazandırıyor. Kod sınıfında da
anma@20 0,1078'den 0,1950'ye çıkıyor. Birleştirmenin kazandığı yer **derinliktir**, kaybettiği yer
**ilk sıradır**, ve bir erişim hattında isteme giren şey ilk birkaç parçadır.

## Birleştirmenin Kaybettirdiği

```python
print("sinif  ilk besin ortak belgesi  ikisi dogru birlesik yanlis")
for kip, S in SINIFLAR.items():
    ortak = kayip = 0
    for q in S:
        ilgili = {i for i, d in enumerate(BELGE) if d["ana"] == q["kavram"]}
        a, g, b = (f(q["metin"]) for _, f in YORDAM)
        ortak += len(set(a[:K]) & set(g[:K]))
        kayip += a[0] in ilgili and g[0] in ilgili and b[0] not in ilgili
    print(f"{kip:6s} {ortak / len(S):>22.2f} {kayip:>28}")

def ilgilisi(q):
    return {i for i, d in enumerate(BELGE) if d["ana"] == q["kavram"]}


q = next(x for x in SINIFLAR["belge"]
         if anahtar_sira(x["metin"])[0] in ilgilisi(x)
         and gomme_sira(x["metin"])[0] in ilgilisi(x)
         and birlesik_sira(x["metin"])[0] not in ilgilisi(x))
print(f"\nsorgu: {q['metin']}  --  hedef kavram: {q['kavram']}")
for ad, f in YORDAM:
    print(f"  {ad:8s}", [f"{BELGE[i]['kod']}/{BELGE[i]['ana']}" for i in f(q["metin"])[:3]])
```

```
sinif  ilk besin ortak belgesi  ikisi dogru birlesik yanlis
abone                    0.20                            1
belge                    1.05                            3
kod                      4.03                            0

sorgu: basinc dususu bolge  --  hedef kavram: basinc
  anahtar  ['AR002/basinc', 'AR015/ekip', 'AR018/basinc']
  gomme    ['AR079/basinc', 'AR088/basinc', 'AR101/ekip']
  birlesik ['AR033/ekip', 'AR015/ekip', 'AR018/basinc']
```

Ortak belge sütunu hiçbir sorguya değil, yordam çiftinin kendisine ait bir sayıdır ve koşumdan
bağımsızdır. Abone dilinde iki listenin ilk beşi ortalama **0,20** belge paylaşıyor: yordamlar
neredeyse hiç anlaşmıyor. Belge dilinde 1,05, yani beşte bir.

Örnek bu sayının sonucunu gösteriyor. Anahtar sözcük AR002'yi, gömme AR079'u ilk sıraya koyuyor;
ikisi de hedef kavramı taşıyor, yani **iki yordam da doğru**. Birleşik ilk sıraya AR033'ü koyuyor
ve o belge `ekip` kavramına ait. AR002 bir listede birinci, öbüründe çok geride; puanı tek bir
büyük terimden geliyor. AR033 ise iki listede de üst sıralarda ama hiçbirinde birinci değil, ve
iki orta terimin toplamı bir büyük terimi geçiyor. Sıra temelli birleştirme **uzlaşma belgesini**
ödüllendirir; iki taraf aynı fikirde değilken ikisinin de ikinci tercihi kazanır. Belge dili
sınıfında bu kırk sorgunun üçünde oluyor, ve ters yönde hiç olmuyor: birleşiğin, iki yordamın da
yanıldığı bir sorguda doğruyu bulduğu tek bir örnek yok. İlk sıradaki dört sorguluk düşüşün
karşılığı sıfır kazançtır.

Kod satırındaki 4,03 tuzaktır. Yüksek örtüşme burada anlaşma değildir: gömme tarafı sıfır
vektörle çalıştığı için listesi saklama sırasıdır, anahtar sözcük tarafının tam eşleşmeden sonraki
kuyruğu da aynı sıradır. İki liste **aynı bilgisiz kuyruğu** paylaşıyor. Birleştirme, iki listenin
aynı olmasıyla ikisinin de boş olmasını ayırt edemez; ayırt edebilseydi bu sınıfta anahtar sözcüğe
tam ağırlık verirdi. Karma arama bir ortalama değil, bir **karar** ister: hangi sorguda hangi
tarafın söz sahibi olduğu.

## Özet

- Üç sorgu sınıfında iki yordam birbirinin tersi yerlerde çalışır: abone dilinde anahtar sözcük
  0,0500 ve gömme 0,5000, kod sorgusunda anahtar sözcük 1,0000 ve gömme 0,0000.
- Kavram yüzeyi taşımayan bir sorgu sıfır vektör üretir; gömme yanılmaz, tanım alanının dışına
  çıkar ve sıralaması saklama sırasına düşer.
- Belge dili sınıfında iki yordam da 0,5000 verirken sıra temelli birleştirme 0,4000 verir;
  birleşik ikisinden de kötüdür ve bu sabit 5, 20 ve 60'ta sürer.
- Nedeni iki listenin ilk beşinin 1,05 belge paylaşmasıdır: iki listede de ikinci sırada duran
  uzlaşma belgesi, birinde birinci olup öbüründe bulunmayan belgeyi geçer.
- Kod sınıfında birleştirme hedef belgenin ilk beşte olma payını 1,0000'den 0,0500'e düşürür;
  bilgisiz bir listeye eşit ağırlık vermek çalışan yordamı da batırır.
- Birleştirme derinlikte kazandırır: belge dilinde anma@20 0,7122'den 0,7209'a çıkar. Kazanç
  yirminci sırada, kayıp ilk sıradadır ve isteme giren ilk sıradır.

## Sonraki Adım

Altı ders boyunca tek bir soru soruldu ve her seferinde daha iyi cevaplandı: dağarcıktaki hangi
parça bu sorguya ait. Gömme bir arama anahtarı oldu, alan uyumu ölçüldü, benzerlik ölçütü seçildi,
dizinin kaybettirdiği sayıldı, süzgecin komşuluğu bozduğu nokta bulundu ve iki sıralamanın
birleşimi tartıldı. Bu derslerin hepsi **erişim** tarafındadır ve hepsinin ölçüsü getirilen
parçanın kendisidir.

Ölçülmeyen şey bundan sonra olandır. Bulunan parça bir isteme konur ve bir modele verilir; o
noktadan itibaren doğru parçanın doğru yanıt ürettiği bir varsayımdır ve bu konuda hiç
sınanmadı. Doğru parça getirildiği hâlde yanlış yanıt üretilebilir, yanlış parça getirildiği hâlde
model şans eseri doğru yanıt verebilir, ve en kötüsü, getirilen parça modelin erişimsiz hâlinden
**daha kötü** bir yanıt üretmesine yol açabilir. Sonraki konu erişim hattını baştan sona kurar ve
ilk dersinde iki sütunu ayırır: doğru parça getirildi mi, ve getirilenle doğru yanıt üretildi mi.
