🔒 maske

Türkçe metinde kişisel veri (PII) tespiti — KVKK odaklı, 9 varlık türü, 19 etiket
Turkish personal-data (PII) detection — KVKK-oriented, 9 entity types, 19 labels

GitHub BERTurk baseline bakeoff license

Türkçe · English

🇹🇷 Türkçe

Genel Bakış

maske, Türkçe serbest metinde dokuz tür kişisel veriyi bulan 19 etiketli bir token sınıflandırma (NER) modelidir: PER, ORG, LOC, ADDR, TC_NO, IBAN, PHONE, PLATE, EMAIL (BIO şeması). Model, 6698 sayılı Kişisel Verilerin Korunması Kanunu'nun (KVKK) maskeleme ve anonimleştirme yükümlülükleri için tasarlanmıştır; müşteri e-postaları, destek kayıtları ve teslim belgeleri gibi gerçek dünya metinlerinde çalışmayı hedefler.

maske projesinin iki katmanlı tasarımındaki NER katmanıdır: kuralların belirleyici biçimle yakaladığı alanlar (TCKN, IBAN) için deterministik bir kural katmanı planlanırken, ek almış isimler (Ayşe'ye, Ahmet'ten) ve adresler gibi esnek varlıklar için bu model sorumludur. Taban model ytu-ce-cosmos/modernbert-tr-base (Apache-2.0, ~150M parametre, 144B Türkçe token) olup gövde ağırlıkları bir WikiANN-tr ince ayarından taşınmış, sınıflandırıcı başı 19 etiket için yeniden başlatılmıştır.

📰 Haberler

  • 27 Ekim 2026 — E-posta tespitini iyileştiren bir eğitim güncellemesi sürüyor (parçalı tespiti düzelten son işlem katmanı + zorlayıcı negatif örnekler). Aşağıdaki gerçek-metin metrikleri eğitim sonrası değerlendirmeyle güncellenecektir.
  • Ekim 2026 — İlk yayın: 19 etiketli KVKK modeli, modernbert-tr-base tabanı, sentetik + WikiANN replay eğitim tarifi.

🏷️ Etiket Şeması

Etiket Açıklama Örnek
PER Kişi adı Ahmet Yılmaz, Ayşe Hanım
ORG Kurum / şirket Kolaykargo A.Ş.
LOC Yer Kadıköy, Ankara
ADDR Açık adres Bağdat Cad. No:12 D:3, Kadıköy/İstanbul
TC_NO T.C. kimlik no (11 hane, sağlama toplamlı) 34628194872
IBAN IBAN (TR + 26 hane, mod-97 geçerli) TR33 0006 1005 1978 6457 8413 26
PHONE Telefon 0532 123 45 67, +90 532 123 45 67
PLATE Araç plakası 34 ABC 123
EMAIL E-posta adresi ad.soyad@firma.com.tr

Her tür B-/I- önekleriyle temsil edilir; toplam 19 etiket (18 + O).

📊 Sonuçlar

Tüm sonuçlar span-exact (birebir eşleşme) ölçütüyle, aynı değerlendirme betikleriyle hesaplanmıştır.

Değerlendirme Micro F1 Ne kanıtlar, ne kanıtlamaz
WikiANN-tr test (replay karışımı) 0.9317 (P 0.9260 / R 0.9374) PER/ORG/LOC yeteneği 7→19 etiket yeniden eğitiminden sağlam çıktı (önceki model: 0.929). Gümüş etiket; PII kıyaslaması değildir.
maske-kvkk-synth test bölümü 1.0000 Üretici içi: eğitim şablonlarıyla aynı, görünmeyen değer dizgileri. Bağlantıların doğru kurulduğunu kanıtlar; gerçek dünya performansı ölçmez.
Werea-KVKK-Bench (çapraz üretici) 0.2617 (P 0.1789 / R 0.4875; 240 satır, eşlenen türler) Farklı bir üretim hattından (Werea-co) cue-yoğun, biçimlendirilmiş veri. Dış sentetik sözleşmeye uyumu ölçer.
Gerçek metin başlangıç seti 0.7805 (P 0.6809 / R 0.9143; 29 doküman / 35 varlık; 8 tuzak dokümanda 7 FP) El ile doğrulanmış 29 düz yazı dokümanı; 11 haneli sipariş no, kart no, VKN, URL içeren boş-altın tuzaklar dahil. Üretime en yakın ölçüm; küçük set.
Gerçek metin — tür bazında P R F1 gold
ADDR – – – 3
EMAIL – – – 2
IBAN – – – 2
LOC – – – 5
ORG – – – 5
PER – – – 7
PHONE – – – 4
PLATE – – – 2
TC_NO – – – 5
MICRO 0.6809 0.9143 0.7805 35

Dürüstlük notu: Yukarıdaki hiçbir sayı doğal olarak oluşmuş Türkçe kişisel veri metninden, ölçekli biçimde gelmemektedir. Eğitim verisi tamamen sentetiktir (nötr taşıyıcı cümlelere varlık enjeksiyonu) ve WikiANN replay karışımı içerir. Bu modeli çözülmüş bir sorun değil, güçlü bir başlangıç noktası olarak değerlendirin.

🚀 Hızlı Başlangıç

# pip install -U transformers accelerate
from transformers import pipeline
import re

pipe = pipeline("token-classification", model="emi08/maske",
                aggregation_strategy="simple")

EMAIL_RE = re.compile(r"[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}")

def detect(text):
    ents = [(e["start"], e["end"], e["entity_group"]) for e in pipe(text)]
    # e-posta kurtarma: parçalı tahminleri tam adresle normalize et
    ents = [x for x in ents if not (x[2] == "EMAIL" and "@" not in text[x[0]:x[1]])]
    for m in EMAIL_RE.finditer(text):
        keep = [x for x in ents if not (x[0] < m.end() and m.start() < x[1])]
        if len(keep) != len(ents):
            ents = keep + [(m.start(), m.end(), "EMAIL")]
    return sorted(ents)

def mask(text):
    out, prev = [], 0
    for s, e, t in detect(text):
        out += [text[prev:s], f"[{t}]"]; prev = e
    return "".join(out) + text[prev:]

print(mask("T.C. kimlik numaram 34628194872, faturayi destek@magazam.com'a gonderin, "
           "telefonum 0532 123 45 67."))
# T.C. kimlik numaram [TC_NO], faturayi [EMAIL]'a gonderin, telefonum [PHONE] .

🛠️ Önerilen Son İşlem: E-posta Kurtarma

Tokenleştirici e-posta adreslerini @ ve . çevresinde alt parçalara böldüğü için model nadiren parçalı e-posta varlıkları üretebilir (örn. yalnız @ veya .com). Yukarıdaki detect() işlevindeki iki kural bu durumu üretimde giderir: (1) @ içermeyen EMAIL tahminleri atılır; (2) geçerli bir e-posta adresiyle çakışan herhangi bir tahmin tam adres aralığına normalize edilir. Ayrıntılı uygulama ve değerlendirme kodu GitHub deposundadır.

🏋️ Eğitim

Öğe Değer
Taban model ytu-ce-cosmos/modernbert-tr-base (Apache-2.0)
Gövde WikiANN-tr ince ayarından taşınan ağırlıklar; 19 etiket için yeniden başlatılan baş
Veri 8.000 sentetik KVKK cümlesi (~%40 varlık yoğunluğu, sağlama toplamlı değerler) + 20.000 WikiANN-tr replay
Bölme 28.000 eğitim / 11.000 doğrulama (karışımdan sonra)
Hiperparametreler 3 epok, LR 2e-5, batch 16, max_len 192, fp32, tek T4
Seçim Doğrulama F1'i en iyi kontrol noktası

🔒 Veri ve Gizlilik Beyanı

Sentetik veri kümesindeki her varlık değeri programatik olarak üretilmiştir: TC kimlik numaraları sağlama toplamı geçerli ancak hiç verilmemiş; IBAN'lar mod-97 geçerli ancak gerçek bir hesaba ait değil; adlar ve adresler kurgusaldır. Eğitim veya değerlendirmede hiçbir gerçek kişinin verisi kullanılmamıştır.

⚠️ Sınırlamalar ve Etik Kullanım

  • Etiket uzayında VKN (vergi kimlik no), pasaport, IP, doğum tarihi, sağlık verisi vb. özel kategori türleri yoktur.
  • Sözcüksel ipucu taşımayan çıplak anılımlar az test edilmiştir.
  • Sentetik taşıyıcılar kısa ve temizdir; uzun belgeler, OCR gürültüsü ve gayri resmî metin ölçülmemiştir.
  • WikiANN etiketleri gümüş/sezgisel etiketlerdir.
  • Bilinen sorun (güncel eğitimde gideriliyor): e-posta adresleri nadiren parçalı yakalanmaktadır; yukarıdaki kurtarma katmanı bunu üretimde çözer.
  • Otomatik maskeleme tek başına KVKK uyumu sağlamaz; tespit ≠ anonimleştirme. Kritik akışlarda insan denetimi gereklidir.

🔗 Kardeş Modeller ve Benzer Çalışmalar

📚 Atıf

@misc{maske_2026,
  author       = {emi08},
  title        = {maske: Turkish Personal Data (PII) Detection for KVKK Workflows},
  year         = {2026},
  url          = {https://huggingface.co/emi08/maske},
}

⚖️ Lisans

Apache-2.0. Taban model ytu-ce-cosmos/modernbert-tr-base Apache-2.0 lisanslıdır; WikiANN katkısı gümüş (otomatik) etiket içerir. Eğitim veri kümesi emi08/maske-kvkk-synth herkese açıktır.

🇬🇧 English

Overview

maske is a 19-label token-classification (NER) model that detects nine types of personal data in Turkish free text: PER, ORG, LOC, ADDR, TC_NO, IBAN, PHONE, PLATE, EMAIL (BIO scheme). It is built for masking and redaction obligations under Turkey's Law No. 6698 on Protection of Personal Data (KVKK) and targets real-world documents: customer e-mails, support tickets, delivery documents. It is the NER layer of the two-layer maske design (a deterministic rule layer for checksum fields is planned separately). Base model is ytu-ce-cosmos/modernbert-tr-base (Apache-2.0, ~150M params, 144B Turkish tokens); body weights were carried over from a WikiANN-tr fine-tune, with the classification head re-initialized for 19 labels.

News

  • Oct 27, 2026 — A training update that fixes the observed e-mail span fragmentation (rescue post-processing + hard negatives) is in progress. Real-text metrics below will be refreshed after the re-evaluation.
  • Oct 2026 — Initial release: 19-label KVKK model on modernbert-tr-base, synthetic + WikiANN replay recipe.

Label Schema

Label Meaning Example
PER Person name Ahmet Yılmaz
ORG Organization Kolaykargo A.Ş.
LOC Location Kadıköy
ADDR Street address Bağdat Cad. No:12 D:3, Kadıköy/İstanbul
TC_NO Turkish ID no (11 digits, checksum-valid) 34628194872
IBAN IBAN (TR + 26 digits, mod-97 valid) TR33 0006 1005 1978 6457 8413 26
PHONE Phone 0532 123 45 67
PLATE License plate 34 ABC 123
EMAIL E-mail address ad.soyad@firma.com.tr

Each type appears with B-/I- prefixes; 19 labels in total (18 + O).

Results

All numbers are span-exact, computed with the same evaluation scripts.

Evaluation Micro F1 What it does / does not prove
WikiANN-tr test (replay mix) 0.9317 (P 0.9260 / R 0.9374) PER/ORG/LOC survived the 7→19 retraining (previous model: 0.929). Silver labels; a regression check, not a PII benchmark.
maske-kvkk-synth test split 1.0000 In-generator: same template skeletons, unseen entity strings. Proves wiring, not real-world performance.
Werea-KVKK-Bench (cross-generator) 0.2617 (P 0.1789 / R 0.4875; 240 rows, mapped types) Different generator (Werea-co); measures conformance to an external synthetic contract.
Real-text starter set 0.7805 (P 0.6809 / R 0.9143; 29 docs / 35 entities; 7 FPs on 8 trap docs) 29 hand-checked prose docs incl. traps (11-digit order numbers, card numbers, VKN, URLs) with empty gold. Closest to production behavior; small set.
Real text — per type P R F1 gold
ADDR – – – 3
EMAIL – – – 2
IBAN – – – 2
LOC – – – 5
ORG – – – 5
PER – – – 7
PHONE – – – 4
PLATE – – – 2
TC_NO – – – 5
MICRO 0.6809 0.9143 0.7805 35

Honesty note: none of these numbers comes from naturally occurring Turkish personal-data text at scale. The training corpus is fully synthetic (entity injection into neutral carriers) mixed with WikiANN replay. Treat this model as a strong baseline, not a solved problem.

Quick Start

from transformers import pipeline
import re

pipe = pipeline("token-classification", model="emi08/maske",
                aggregation_strategy="simple")

EMAIL_RE = re.compile(r"[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}")

def detect(text):
    ents = [(e["start"], e["end"], e["entity_group"]) for e in pipe(text)]
    ents = [x for x in ents if not (x[2] == "EMAIL" and "@" not in text[x[0]:x[1]])]
    for m in EMAIL_RE.finditer(text):
        keep = [x for x in ents if not (x[0] < m.end() and m.start() < x[1])]
        if len(keep) != len(ents):
            ents = keep + [(m.start(), m.end(), "EMAIL")]
    return sorted(ents)

def mask(text):
    out, prev = [], 0
    for s, e, t in detect(text):
        out += [text[prev:s], f"[{t}]"]; prev = e
    return "".join(out) + text[prev:]

print(mask("T.C. kimlik numaram 34628194872, faturayi destek@magazam.com'a gonderin, "
           "telefonum 0532 123 45 67."))
# T.C. kimlik numaram [TC_NO], faturayi [EMAIL]'a gonderin, telefonum [PHONE] .

Recommended Post-processing: E-mail Rescue

Because the tokenizer splits e-mail addresses around @ and ., the model can occasionally emit fragmented e-mail spans (e.g. only @ or .com). The two rules in detect() above fix this in production: (1) drop EMAIL predictions containing no @; (2) normalize any prediction overlapping a well-formed e-mail address to the full address span. Full implementation and evaluation code live in the GitHub repo.

Training

Item Value
Base model ytu-ce-cosmos/modernbert-tr-base (Apache-2.0)
Body Weights carried from a WikiANN-tr fine-tune; head re-initialized for 19 labels
Data 8,000 synthetic KVKK sentences (~40% entity density, checksum-valid values) + 20,000 WikiANN-tr replay
Splits 28,000 train / 11,000 val after mixing
Hyperparameters 3 epochs, LR 2e-5, batch 16, max_len 192, fp32, single T4
Selection Best checkpoint by validation F1

Data & Privacy Statement

Every entity value in the synthetic corpus was generated programmatically: TC IDs are checksum-valid but never issued, IBANs pass mod-97 but belong to no real account, names and addresses are fictional. No real person's data was used in training or evaluation.

Limitations & Ethical Use

  • No VKN (tax number), passport, IP, date-of-birth, health or other special-category types in the label space.
  • Bare mentions without lexical cues are under-tested.
  • Synthetic carriers are short and clean; long documents, OCR noise and informal text are unmeasured.
  • WikiANN labels are silver/heuristic.
  • Known issue (being fixed in the current retrain): e-mails were occasionally detected as fragments; the rescue layer above addresses this in production.
  • Automated masking does not by itself guarantee KVKK compliance; detection ≠ anonymization. Human review remains necessary.

Related Models

Citation

@misc{maske_2026,
  author       = {emi08},
  title        = {maske: Turkish Personal Data (PII) Detection for KVKK Workflows},
  year         = {2026},
  url          = {https://huggingface.co/emi08/maske},
}

License

Apache-2.0. Base model ytu-ce-cosmos/modernbert-tr-base is Apache-2.0; the WikiANN contribution contains silver (auto-generated) labels. The training dataset emi08/maske-kvkk-synth is public.

Downloads last month
40
Safetensors
Model size
0.1B params
Tensor type
F32
·
Inference Providers NEW
This model isn't deployed by any Inference Provider. 🙋 Ask for provider support

Model tree for emi08/maske

Finetuned
(11)
this model