---
title: 'Zaman ve Metin Öznitelikleri'
source: 'https://academia.sh/tr/kurslar/oznitelik-muhendisligi/zaman-ve-metin-oznitelikleri'
course: 'Veri Hazırlama ve Öznitelik Mühendisliği'
language: tr
updated: '2026-08-17T18:10:11+00:00'
license: 'CC BY-SA 4.0'
---

# Zaman ve Metin Öznitelikleri

Bir tarihten ve bir kısa metinden beşer sayı çıkarıp toplam katkılarının ayrılmış kümede sayılması: karar öncesi çizgi 0,7897 iken tarihten çıkan beş sayı 0,0198 kaybettiriyor, nottan çıkan beş sayı 0,0317 katıyor, on sayı birlikte 0,0198 katıyor. Katkının tamamı tek bir göstergeden geliyor; mühür izi göstergesi tek başına 0,0357 katarken metin uzunluğu 0,0357 ve sözcük sayısı 0,0516 kaybettiriyor. Bir alandan kaç sayı çıktığı katkıyı belirlemiyor, alanın etiketle ilişkisi belirliyor.

Önceki ders altı öznitelik üretti, altısını da tek tek ölçtü ve geriye tek bir sütun kaldı: kişi
başına tüketim, karar öncesi çizgiyi 0,7778'den 0,7897'ye taşıyan oran özniteliği. Öteki beşi
kümeden çıkarıldı. Karar öncesi çizgi bu dersten itibaren **on iki sütunun** çizgisidir.

Abone tablosunda modele verilmemiş iki alan daha var ve ikisi de sayı değil: sözleşmenin
başladığı **tarih** ve saha ekibinin okuma sırasında bıraktığı **kısa not**. Bir karar ağacı
bunların hiçbirini olduğu gibi bölemez; tarih bir sıralı değerdir ama sıralaması yılın
dönemselliğini taşımaz, metin ise hiç sıralı değildir. İkisinden de birden çok sayı çıkarılabilir
ve bu dersin ölçüsü tam olarak budur: **bir alandan kaç sayı çıkıyor ve o sayıların toplam
katkısı ne.**

- **OS8.** Karar öncesi çizgi on iki sütundur: M27/K01'in on bir sütunu ve `kisi_basi`. Model
  değişmez: derinlik 6 karar ağacı. Taban çizgisi 0,7579'dur.
- **OS9.** Sözleşme tarihi ve saha notu **kurgudur**, aynı tohumdan (20260218) abone numarasına
  bağlı olarak üretilir ve tabloya bu derste eklenir.
- **OS10.** Saha notu **okuma döneminde** yazılır; şüphe etiketi dönem kapandıktan sonra
  kesinleşir. Notun içeriği tahmin anında eldedir.
- **OS11.** Mühür izi kaydı şüpheli abonelerde 0,42, ötekilerde 0,10 olasılıkla nota girer;
  erişim kaydı dönem sayısı üçten azsa 0,30, değilse 0,08 olasılıkla girer.
- **OS12.** Araç kaydı 0,25 olasılıkla girer ve etiketten **bağımsızdır**; tuzak göstergedir.
- **OS13.** Metin işlemleri M26/K04'ün veri çerçeveleri kursunda kuruldu; burada dizgi yordamı
  tekrarlanmaz, yalnız metinden çıkan sayı ölçülür. Sözcük torbası ve gömme uzayı bu kursun
  konusu değildir.
- **OS14.** Katkı, on iki sütunun ayrılmış kümedeki sayısından farktır; bir satır 0,0040'tır.

## Bir Tarihten Beş, Bir Nottan Beş Sayı

Kurulum önceki derslerinkiyle aynı kümeyi üretir; tek fark, kalıcı olduğu ölçülmüş `kisi_basi`
sütununun baştan eklenmiş olmasıdır.

```python
# ORTAK — MODELDIR. M27/K01'in KURGU abone tablosu ayni tohumla yeniden uretilir;
# model derinlik 6 karar agacidir. Onceki dersten kalan tek yeni sutun kisi_basi.
import math

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 = {"no": k["no"], "hane": k["hane"], "memnuniyet": k["memnuniyet"],
         "donem": len(v), "ort_tuketim": round(ort, 2), "oynaklik": round(oyn, 2),
         "sifir_okuma": int(min(v) == 0.0), "supheli": int(z > 1.35),
         "bolge_ad": k["bolge"][0]}
    for b in BOLGE:
        x["b_" + b[0]] = int(k["bolge"][0] == b[0])
    VERI.append(x)

TEMEL = ["ort_tuketim", "oynaklik", "hane", "memnuniyet", "donem", "sifir_okuma",
         "b_kuzey", "b_guney", "b_dogu", "b_bati", "b_merkez"]
TABAN_ALAN = TEMEL + ["kisi_basi"]
for x in VERI:
    x["kisi_basi"] = round(x["ort_tuketim"] / x["hane"], 3)


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, DOG, SIN = K[:756], K[756:1008], K[1008:]


def gini(s):
    p = sum(x["supheli"] for x in s) / len(s) if s else 0.0
    return 2 * p * (1 - p)


def agac(s, derinlik, alanlar, enaz=2):
    p, en = sum(x["supheli"] for x in s) / len(s), None
    if derinlik and len(s) >= 2 * enaz and 0.0 < p < 1.0:
        for a in alanlar:
            d = sorted({x[a] for x in s})
            for v in (d[1:] if len(d) < 10 else
                      [d[int(i * len(d) / 10)] for i in range(1, 10)]):
                sol = [x for x in s if x[a] < v]
                sag = [x for x in s if x[a] >= v]
                if min(len(sol), len(sag)) < enaz:
                    continue
                k = gini(s) - (len(sol) * gini(sol) + len(sag) * gini(sag)) / len(s)
                if en is None or k > en[0]:
                    en = (k, a, v, sol, sag)
    if en is None or en[0] <= 1e-9:
        return {"tahmin": int(p > 0.5)}
    return {"alan": en[1], "esik": en[2],
            "sol": agac(en[3], derinlik - 1, alanlar, enaz),
            "sag": agac(en[4], derinlik - 1, alanlar, enaz)}


def tahmin(d, x):
    while "tahmin" not in d:
        d = d["sol"] if x[d["alan"]] < d["esik"] else d["sag"]
    return d["tahmin"]


def dogruluk(d, s):
    return sum(tahmin(d, x) == x["supheli"] for x in s) / len(s)


def taban(egt, s):
    c = int(sum(x["supheli"] for x in egt) * 2 > len(egt))
    return sum(x["supheli"] == c for x in s) / len(s)


def olc(alanlar, derinlik=6):
    m = agac(EGT, derinlik, alanlar)
    return dogruluk(m, EGT), dogruluk(m, SIN)
```

Tarihten çıkarılan beş sayı iki farklı soruya karşılık gelir. Ay, çeyrek, haftanın günü ve yılın
kaçıncı günü **dönemsel** göstergelerdir: aynı tarih her yıl aynı değeri verir ve amaçları
mevsimlik bir düzeni yakalamaktır. Sözleşme yaşı ise **doğrusal** bir sayıdır ve her gün büyür.
Nottan çıkarılan beş sayı da iki gruba ayrılır: iki tanesi metnin **biçimini** ölçer (karakter
sayısı, sözcük sayısı), üç tanesi belirli bir **anahtar sözcüğün** varlığını gösterir.

```python
import datetime

BAS = datetime.date(2024, 1, 1)
KOK = ["sayac erisimi saglandi", "okuma normal", "abone evde degildi",
       "kapak kirli", "olcum tekrarlandi", "vana kontrol edildi"]
EK = ["arac park halinde", "kapi zili calismiyor", "bahce kapisi acik"]

for x in VERI:
    r = uretec(TOHUM + 61000 + x["no"])
    x["sozlesme_gun"] = int(r() * 1460)
    g = BAS + datetime.timedelta(days=x["sozlesme_gun"])
    x["ay"], x["ceyrek"] = g.month, (g.month - 1) // 3 + 1
    x["hafta_gunu"], x["yil_ici_gun"] = g.weekday(), g.timetuple().tm_yday
    x["sozlesme_yasi"] = 1460 - x["sozlesme_gun"]
    p = [KOK[int(r() * len(KOK))]]
    if r() < (0.42 if x["supheli"] else 0.10):
        p.append("muhur izi var")
    if r() < (0.30 if x["donem"] < 3 else 0.08):
        p.append("erisim saglanamadi")
    if r() < 0.25:
        p.append(EK[int(r() * len(EK))])
    n = ", ".join(p)
    x["saha_notu"], x["not_uzunluk"], x["not_sozcuk"] = n, len(n), len(n.split())
    x["a_muhur"] = int("muhur" in n)
    x["a_erisim"] = int("erisim saglanamadi" in n)
    x["a_arac"] = int("arac" in n)

ZAMAN = ["ay", "ceyrek", "hafta_gunu", "yil_ici_gun", "sozlesme_yasi"]
METIN = ["not_uzunluk", "not_sozcuk", "a_muhur", "a_erisim", "a_arac"]
for i in (4, 9, 10):
    print(f"not ornegi: {VERI[i]['saha_notu']}")
print(f"muhur izi kayitli {sum(x['a_muhur'] for x in VERI)} satir; suphelilerin "
      f"{sum(x['a_muhur'] for x in VERI if x['supheli']) / sum(x['supheli'] for x in VERI):.3f}"
      f"'unde, otekilerin "
      f"{sum(x['a_muhur'] for x in VERI if not x['supheli']) / sum(1 - x['supheli'] for x in VERI):.3f}"
      f"'unde\n")
ONCE = olc(TABAN_ALAN)
print(f"{'blok':<16} {'sayi':>4} {'egitimde':>9} {'ayrilmis':>9} {'katki':>8}")
print(f"{'-- yok --':<16} {0:>4} {ONCE[0]:>9.4f} {ONCE[1]:>9.4f}")
for ad, al in (("tarihten", ZAMAN), ("metinden", METIN), ("ikisi", ZAMAN + METIN)):
    e, s = olc(TABAN_ALAN + al)
    print(f"{ad:<16} {len(al):>4} {e:>9.4f} {s:>9.4f} {s - ONCE[1]:>+8.4f}")
```

```
not ornegi: olcum tekrarlandi
not ornegi: abone evde degildi, erisim saglanamadi, arac park halinde
not ornegi: kapak kirli, muhur izi var
muhur izi kayitli 219 satir; suphelilerin 0.453'unde, otekilerin 0.096'unde

blok             sayi  egitimde  ayrilmis    katki
-- yok --           0    0.8519    0.7897
tarihten            5    0.8611    0.7698  -0.0198
metinden            5    0.8942    0.8214  +0.0317
ikisi              10    0.8955    0.8095  +0.0198
```

Üç sayı yan yana durunca alan sayısıyla katkı arasında bağ olmadığı görünüyor. İki alandan beşer
sayı çıktı; biri 0,0317 kazandırdı, öteki 0,0198 kaybettirdi. On sayı birlikte verildiğinde toplam
katkı 0,0198'e iniyor — yani tarih alanı, metin alanının kazandırdığının tam yarısını geri
alıyor. Eğitim sayısı ise her üç kurulumda da yükseliyor: 0,8519'dan 0,8955'e. Sütun sayısı arttıkça
eğitim sayısının artması ölçüm değil, tanımın gereğidir.

Tarih bloğunun eksi çıkması şaşırtıcı değildir, çünkü bu kurguda sözleşme tarihi ile şüphe
arasında hiçbir bağ kurulmamıştır. Kaybın nedeni bağın yokluğu değil, **beş sütunun bölme adayı
olarak yarışması**: yılın kaçıncı günü sütununun 366 ayrı değeri vardır ve bu kadar çok eşik
adayı arasından eğitim kümesinde iyi görünen bir tanesini bulmak kolaydır. Çok değerli bir gürültü
sütunu, az değerli bir gürültü sütunundan daha tehlikelidir.

## Katkı Nereden Geliyor

Bloklar tek tek açıldığında toplam sayıların hangi sütundan geldiği görünür.

```python
print(f"{'tek oznitelik':<16} {'kaynak':<8} {'egitimde':>9} {'ayrilmis':>9} {'katki':>8}")
for a in ZAMAN + METIN:
    e, s = olc(TABAN_ALAN + [a])
    print(f"{a:<16} {'tarih' if a in ZAMAN else 'metin':<8} {e:>9.4f} {s:>9.4f} "
          f"{s - ONCE[1]:>+8.4f}")
for ad, al in (("yalniz uc anahtar", ["a_muhur", "a_erisim", "a_arac"]),
               ("yalniz iki sayac", ["not_uzunluk", "not_sozcuk"]),
               ("yalniz muhur", ["a_muhur"])):
    e, s = olc(TABAN_ALAN + al)
    print(f"\n{ad:<18} {e:.4f} {s:.4f} {s - ONCE[1]:+.4f}", end="")
print()
```

```
tek oznitelik    kaynak    egitimde  ayrilmis    katki
ay               tarih       0.8519    0.7897  +0.0000
ceyrek           tarih       0.8519    0.7897  +0.0000
hafta_gunu       tarih       0.8532    0.7778  -0.0119
yil_ici_gun      tarih       0.8519    0.7897  +0.0000
sozlesme_yasi    tarih       0.8585    0.7817  -0.0079
not_uzunluk      metin       0.8823    0.7540  -0.0357
not_sozcuk       metin       0.8783    0.7381  -0.0516
a_muhur          metin       0.8876    0.8254  +0.0357
a_erisim         metin       0.8519    0.7857  -0.0040
a_arac           metin       0.8519    0.7897  +0.0000

yalniz uc anahtar  0.8876 0.8254 +0.0357
yalniz iki sayac   0.8942 0.7381 -0.0516
yalniz muhur       0.8876 0.8254 +0.0357
```

On özniteliğin dokuzu sıfır ya da eksi katkı veriyor. Kazancın tamamı `a_muhur` sütunundan
geliyor: tek başına 0,0357, yani dokuz abone. Üç anahtar sözcük göstergesi birlikte de 0,0357
veriyor ve yalnız mühür göstergesi de 0,0357 veriyor — öteki iki anahtar hiçbir şey eklemiyor.
Sayının kaynağı belli: mühür izi şüphelilerin 0,453'ünde, ötekilerin 0,096'sında kayıtlı, yani
bu gösterge etiketle ilişkilidir. Araç kaydı ise etiketten bağımsız üretildi ve katkısı tam sıfır
çıktı; tuzak gösterge tuzak olarak davrandı.

En sert satırlar metnin **biçim** ölçüleridir. Karakter sayısı 0,0357, sözcük sayısı 0,0516
kaybettiriyor; ikisi birlikte 0,0516 kaybettiriyor ve eğitim sayısını 0,8942'ye çıkarıyor. Bu iki
sütun aslında anahtar sözcük göstergelerinin bulanık bir kopyasıdır: not uzarsa içinde ek bir kayıt
var demektir, ama hangi kayıt olduğu belli değildir. Model uzunluğu kullanarak eğitim kümesinde
mühür kaydını dolaylı yoldan tahmin ediyor ve ayrılmış kümede bu dolaylı yol tutmuyor. Bir metinden
sayı çıkarmanın kolay yolu ile işe yarayan yolu aynı yol değildir.

Bir alandan çıkan sayı adedi, o alanın katkısını ölçmez. On sayı çıkarıldı, katkının tamamı
bir tanesinden geldi, öteki dokuz sayı toplamda 0,0159 götürdü. Alan başına sütun sayısını
artırmak modele daha çok bilgi vermez, daha çok **arama alanı** verir.

## Notun Zamanı

Mühür göstergesi ile M27/K01'in sızıntı dersindeki denetim sütunu istatistik olarak aynı biçime
sahiptir: ikisi de şüpheli abonelerde daha sık görünen bir gösterge sütunudur. Aralarındaki tek
fark **zamandır**. Denetim ataması etiket kesinleştikten sonra yazılıyordu ve o yüzden sızıntıydı;
saha notu okuma döneminde, etiket kesinleşmeden yazılır ve tahminin verileceği anda kayıttadır.

Bu ayrım tabloya bakarak yapılamaz. Şişme ile katkı ayrılmış kümede aynı işareti taşır ve aynı
sütunda görünür. Ayrımı yalnız kaynak sistemin **yazma sırası** verir: bu değer hangi olaydan
sonra kaydediliyor. Sorunun kendisi M27/K01'de kuruldu; bu ders onu bir öznitelik üretme kararının
parçası hâline getiriyor. Metinden çıkarılan her gösterge için soru yeniden sorulur, çünkü aynı
metin alanı hem dönem içinde hem dönem sonrasında yazılan cümleleri taşıyabilir.

Sözcük torbası ve gömme uzayı gibi metni bütünüyle sayıya çeviren yöntemler bu kursun konusu
değildir; onlar M27/K06'da ele alınır. Burada ölçülen şey daha dar ve daha yaygın bir karardır:
elde bir serbest metin alanı varken ondan **birkaç gösterge** çıkarmak. Ölçüm bu kararın da
katkısız olabileceğini gösteriyor.

## Özet

- Bir tarihten beş, bir kısa nottan beş öznitelik çıkarıldı; tarih bloğu 0,0198 kaybettirdi, metin
  bloğu 0,0317 katkı verdi, on sayı birlikte 0,0198 verdi.
- Katkının tamamı tek bir göstergeden geliyor: mühür izi tek başına 0,0357 katıyor, üç anahtar
  gösterge birlikte de aynı sayıyı veriyor, etiketten bağımsız üretilen araç göstergesi tam sıfır.
- Metnin biçim ölçüleri en çok kaybettiren sütunlar: karakter sayısı 0,0357, sözcük sayısı 0,0516;
  ikisi de anahtar göstergenin bulanık kopyasıdır ve eğitim sayısını 0,8942'ye çıkarır.
- Çok değerli bir gürültü sütunu az değerli olandan daha tehlikelidir; yılın kaçıncı günü sütunu
  366 eşik adayı sunar ve eğitim kümesinde iyi görünen bir tanesi kolay bulunur.
- Mühür göstergesi ile M27/K01'in denetim sütunu aynı biçimdedir; ayrımı yalnız kaydın zamanı
  verir ve bu soru her metin özniteliği için yeniden sorulur.

## Sonraki Adım

İki derste sütun sayısı on birden yirmi ikiye çıktı ve her seferinde ölçüm aynı şeyi söyledi:
sütunların çoğu ya hiçbir şey katmıyor ya da kaybettiriyor. Buraya kadar sütunlar **tek tek elle**
elendi. Elemenin kendisi bir yordama bağlanabilir — sütunlar etiketle ilişkilerine göre süzülebilir,
model tekrar tekrar eğitilerek denenebilir ya da modelin kendi öznitelik önemi okunabilir. Üç
yöntem aynı kümede kaç sütun seçer, seçim **bütün kümeden** yapıldığında ayrılmış küme sayısı ne
kadar şişer ve **yalnız eğitimden** yapıldığında ne olur — sonraki ders bunu ölçer.
